Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
package httpapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/descrybe/descrybe-v2/apps/api/internal/catalog"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (s *Server) handleListFieldGroups(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
items, err := s.Catalog.ListFieldGroups(r.Context(), cid)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "list failed")
|
||||
return
|
||||
}
|
||||
limit, offset := ParseLimitOffsetMax(r, maxTreePageLimit)
|
||||
page, total := pageSlice(items, limit, offset)
|
||||
JSON(w, http.StatusOK, map[string]any{"groups": page, "total": total, "limit": limit, "offset": offset})
|
||||
}
|
||||
|
||||
func (s *Server) handleCreateFieldGroup(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
var body map[string]any
|
||||
if err := DecodeJSON(r, &body); err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
name, _ := body["name"].(string)
|
||||
var desc *string
|
||||
if v, ok := body["description"]; ok {
|
||||
if v == nil {
|
||||
empty := ""
|
||||
desc = &empty
|
||||
} else if str, ok := v.(string); ok {
|
||||
desc = &str
|
||||
}
|
||||
}
|
||||
order := 0
|
||||
if v, ok := body["order"].(float64); ok {
|
||||
order = int(v)
|
||||
}
|
||||
item, err := s.Catalog.CreateFieldGroup(r.Context(), cid, name, desc, order)
|
||||
if err != nil {
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not create field group", err, catalog.ClientError)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusCreated, item)
|
||||
}
|
||||
|
||||
func (s *Server) handleUpdateFieldGroup(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
id, err := uuid.Parse(chi.URLParam(r, "id"))
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid id")
|
||||
return
|
||||
}
|
||||
var body map[string]any
|
||||
if err := DecodeJSON(r, &body); err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
item, err := s.Catalog.UpdateFieldGroup(r.Context(), cid, id, body)
|
||||
if errors.Is(err, catalog.ErrNotFound) {
|
||||
Error(w, http.StatusNotFound, "not found")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, catalog.ErrSystemImmutable) {
|
||||
Error(w, http.StatusForbidden, err.Error())
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not update field group", err, catalog.ClientError)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, item)
|
||||
}
|
||||
|
||||
func (s *Server) handleDeleteFieldGroup(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
id, err := uuid.Parse(chi.URLParam(r, "id"))
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid id")
|
||||
return
|
||||
}
|
||||
err = s.Catalog.DeleteFieldGroup(r.Context(), cid, id)
|
||||
if errors.Is(err, catalog.ErrNotFound) {
|
||||
Error(w, http.StatusNotFound, "not found")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, catalog.ErrSystemImmutable) {
|
||||
Error(w, http.StatusForbidden, err.Error())
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "delete failed")
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
func (s *Server) handleListStandardFields(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
enabledOnly := false
|
||||
switch strings.ToLower(strings.TrimSpace(r.URL.Query().Get("enabled"))) {
|
||||
case "1", "true", "yes":
|
||||
enabledOnly = true
|
||||
}
|
||||
items, err := s.Catalog.ListStandardFields(r.Context(), cid, enabledOnly)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "list failed")
|
||||
return
|
||||
}
|
||||
limit, offset := ParseLimitOffsetMax(r, maxTreePageLimit)
|
||||
page, total := pageSlice(items, limit, offset)
|
||||
JSON(w, http.StatusOK, map[string]any{"fields": page, "total": total, "limit": limit, "offset": offset})
|
||||
}
|
||||
|
||||
func (s *Server) handleCreateStandardField(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
var body map[string]any
|
||||
if err := DecodeJSON(r, &body); err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
item, err := s.Catalog.CreateStandardField(r.Context(), cid, body)
|
||||
if err != nil {
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not create standard field", err, catalog.ClientError)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusCreated, item)
|
||||
}
|
||||
|
||||
func (s *Server) handleUpdateStandardField(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
id, err := uuid.Parse(chi.URLParam(r, "id"))
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid id")
|
||||
return
|
||||
}
|
||||
var body map[string]any
|
||||
if err := DecodeJSON(r, &body); err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
item, err := s.Catalog.UpdateStandardField(r.Context(), cid, id, body)
|
||||
if errors.Is(err, catalog.ErrNotFound) {
|
||||
Error(w, http.StatusNotFound, "not found")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, catalog.ErrSystemImmutable) {
|
||||
Error(w, http.StatusForbidden, err.Error())
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not update standard field", err, catalog.ClientError)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, item)
|
||||
}
|
||||
|
||||
func (s *Server) handleDeleteStandardField(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
id, err := uuid.Parse(chi.URLParam(r, "id"))
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid id")
|
||||
return
|
||||
}
|
||||
err = s.Catalog.DeleteStandardField(r.Context(), cid, id)
|
||||
if errors.Is(err, catalog.ErrNotFound) {
|
||||
Error(w, http.StatusNotFound, "not found")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, catalog.ErrSystemImmutable) {
|
||||
Error(w, http.StatusForbidden, err.Error())
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "delete failed")
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
func (s *Server) handleBulkStandardFieldsEnabled(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
var body struct {
|
||||
IDs []string `json:"ids"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
}
|
||||
if err := DecodeJSON(r, &body); err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
if body.Enabled == nil {
|
||||
Error(w, http.StatusBadRequest, "enabled required")
|
||||
return
|
||||
}
|
||||
ids := make([]uuid.UUID, 0, len(body.IDs))
|
||||
for _, raw := range body.IDs {
|
||||
id, err := uuid.Parse(strings.TrimSpace(raw))
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid id")
|
||||
return
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
n, err := s.Catalog.BulkSetStandardFieldsEnabled(r.Context(), cid, ids, *body.Enabled)
|
||||
if err != nil {
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not update standard fields", err, catalog.ClientError)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]any{"updated": n, "enabled": *body.Enabled})
|
||||
}
|
||||
|
||||
func (s *Server) handleEnableRecommendedStandardFields(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
items, err := s.Catalog.EnableRecommendedEcommerce(r.Context(), cid)
|
||||
if err != nil {
|
||||
LogAndError(w, http.StatusInternalServerError, "enable recommended fields failed", err)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]any{"fields": items, "status": "ok"})
|
||||
}
|
||||
|
||||
func (s *Server) handleListStructuredDescriptions(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
items, err := s.Catalog.ListStructuredDescriptions(r.Context(), cid)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "list failed")
|
||||
return
|
||||
}
|
||||
limit, offset := ParseLimitOffsetMax(r, maxTreePageLimit)
|
||||
page, total := pageSlice(items, limit, offset)
|
||||
JSON(w, http.StatusOK, map[string]any{"fields": page, "total": total, "limit": limit, "offset": offset})
|
||||
}
|
||||
|
||||
func (s *Server) handleCreateStructuredDescription(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
var body map[string]any
|
||||
if err := DecodeJSON(r, &body); err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
fieldKey := ""
|
||||
if v, ok := body["field_key"].(string); ok {
|
||||
fieldKey = v
|
||||
} else if v, ok := body["fieldKey"].(string); ok {
|
||||
fieldKey = v
|
||||
}
|
||||
typ := "text"
|
||||
if v, ok := body["type"].(string); ok && v != "" {
|
||||
typ = v
|
||||
}
|
||||
item, err := s.Catalog.CreateStructuredDescription(r.Context(), cid, fieldKey, typ)
|
||||
if err != nil {
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not create structured description", err, catalog.ClientError)
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusCreated, item)
|
||||
}
|
||||
|
||||
func (s *Server) handleDeleteStructuredDescription(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
id, err := uuid.Parse(chi.URLParam(r, "id"))
|
||||
if err != nil {
|
||||
Error(w, http.StatusBadRequest, "invalid id")
|
||||
return
|
||||
}
|
||||
err = s.Catalog.DeleteStructuredDescription(r.Context(), cid, id)
|
||||
if errors.Is(err, catalog.ErrNotFound) {
|
||||
Error(w, http.StatusNotFound, "not found")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "delete failed")
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
Reference in New Issue
Block a user