選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

205 行
6.0KB

  1. package handlers
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "github.com/go-chi/chi/v5"
  7. "qctextbuilder/internal/buildsvc"
  8. "qctextbuilder/internal/onboarding"
  9. "qctextbuilder/internal/templatesvc"
  10. )
  11. type API struct {
  12. templateSvc *templatesvc.Service
  13. onboardSvc *onboarding.Service
  14. buildSvc buildsvc.Service
  15. }
  16. func NewAPI(templateSvc *templatesvc.Service, onboardSvc *onboarding.Service, buildSvc buildsvc.Service) *API {
  17. return &API{
  18. templateSvc: templateSvc,
  19. onboardSvc: onboardSvc,
  20. buildSvc: buildSvc,
  21. }
  22. }
  23. func (a *API) Health(w http.ResponseWriter, _ *http.Request) {
  24. writeJSON(w, http.StatusOK, map[string]any{"status": "ok"})
  25. }
  26. func (a *API) SyncTemplates(w http.ResponseWriter, r *http.Request) {
  27. templates, err := a.templateSvc.SyncAITemplates(r.Context())
  28. if err != nil {
  29. writeJSON(w, http.StatusBadGateway, map[string]any{"error": err.Error()})
  30. return
  31. }
  32. writeJSON(w, http.StatusOK, map[string]any{"count": len(templates), "templates": templates})
  33. }
  34. func (a *API) ListTemplates(w http.ResponseWriter, r *http.Request) {
  35. templates, err := a.templateSvc.ListTemplates(r.Context())
  36. if err != nil {
  37. writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
  38. return
  39. }
  40. writeJSON(w, http.StatusOK, map[string]any{"count": len(templates), "templates": templates})
  41. }
  42. func (a *API) GetTemplateDetail(w http.ResponseWriter, r *http.Request) {
  43. rawID := chi.URLParam(r, "id")
  44. templateID, err := strconv.ParseInt(rawID, 10, 64)
  45. if err != nil {
  46. writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid template id"})
  47. return
  48. }
  49. detail, err := a.templateSvc.GetTemplateDetail(r.Context(), templateID)
  50. if err != nil {
  51. writeJSON(w, http.StatusNotFound, map[string]any{"error": err.Error()})
  52. return
  53. }
  54. writeJSON(w, http.StatusOK, detail)
  55. }
  56. func (a *API) OnboardTemplate(w http.ResponseWriter, r *http.Request) {
  57. rawID := chi.URLParam(r, "id")
  58. templateID, err := strconv.ParseInt(rawID, 10, 64)
  59. if err != nil {
  60. writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid template id"})
  61. return
  62. }
  63. manifest, fields, err := a.onboardSvc.OnboardTemplate(r.Context(), templateID)
  64. if err != nil {
  65. writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
  66. return
  67. }
  68. writeJSON(w, http.StatusOK, map[string]any{
  69. "manifestId": manifest.ID,
  70. "fieldCount": len(fields),
  71. "status": "reviewed",
  72. })
  73. }
  74. type updateTemplateFieldsRequest struct {
  75. ManifestID string `json:"manifestId"`
  76. Fields []updateTemplateFieldItem `json:"fields"`
  77. }
  78. type updateTemplateFieldItem struct {
  79. Path string `json:"path"`
  80. IsEnabled *bool `json:"isEnabled,omitempty"`
  81. IsRequiredByUs *bool `json:"isRequiredByUs,omitempty"`
  82. DisplayLabel *string `json:"displayLabel,omitempty"`
  83. DisplayOrder *int `json:"displayOrder,omitempty"`
  84. Notes *string `json:"notes,omitempty"`
  85. }
  86. func (a *API) UpdateTemplateFields(w http.ResponseWriter, r *http.Request) {
  87. rawID := chi.URLParam(r, "id")
  88. templateID, err := strconv.ParseInt(rawID, 10, 64)
  89. if err != nil {
  90. writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid template id"})
  91. return
  92. }
  93. var req updateTemplateFieldsRequest
  94. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  95. writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid JSON body"})
  96. return
  97. }
  98. if len(req.Fields) == 0 {
  99. writeJSON(w, http.StatusBadRequest, map[string]any{"error": "fields is required"})
  100. return
  101. }
  102. patches := make([]onboarding.FieldPatch, 0, len(req.Fields))
  103. for _, f := range req.Fields {
  104. patches = append(patches, onboarding.FieldPatch{
  105. Path: f.Path,
  106. IsEnabled: f.IsEnabled,
  107. IsRequiredByUs: f.IsRequiredByUs,
  108. DisplayLabel: f.DisplayLabel,
  109. DisplayOrder: f.DisplayOrder,
  110. Notes: f.Notes,
  111. })
  112. }
  113. manifest, fields, err := a.onboardSvc.UpdateTemplateFields(r.Context(), templateID, req.ManifestID, patches)
  114. if err != nil {
  115. writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
  116. return
  117. }
  118. writeJSON(w, http.StatusOK, map[string]any{
  119. "templateId": templateID,
  120. "manifestId": manifest.ID,
  121. "fieldCount": len(fields),
  122. "fields": fields,
  123. })
  124. }
  125. func (a *API) StartBuild(w http.ResponseWriter, r *http.Request) {
  126. var req buildsvc.StartBuildRequest
  127. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  128. writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid JSON body"})
  129. return
  130. }
  131. result, err := a.buildSvc.StartBuild(r.Context(), req)
  132. if err != nil {
  133. writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
  134. return
  135. }
  136. writeJSON(w, http.StatusAccepted, result)
  137. }
  138. func (a *API) GetBuild(w http.ResponseWriter, r *http.Request) {
  139. buildID := chi.URLParam(r, "id")
  140. build, err := a.buildSvc.GetBuild(r.Context(), buildID)
  141. if err != nil {
  142. writeJSON(w, http.StatusNotFound, map[string]any{"error": err.Error()})
  143. return
  144. }
  145. writeJSON(w, http.StatusOK, build)
  146. }
  147. func (a *API) PollBuildOnce(w http.ResponseWriter, r *http.Request) {
  148. buildID := chi.URLParam(r, "id")
  149. if err := a.buildSvc.PollOnce(r.Context(), buildID); err != nil {
  150. writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
  151. return
  152. }
  153. build, err := a.buildSvc.GetBuild(r.Context(), buildID)
  154. if err != nil {
  155. writeJSON(w, http.StatusNotFound, map[string]any{"error": err.Error()})
  156. return
  157. }
  158. writeJSON(w, http.StatusOK, build)
  159. }
  160. func (a *API) FetchBuildEditorURL(w http.ResponseWriter, r *http.Request) {
  161. buildID := chi.URLParam(r, "id")
  162. if err := a.buildSvc.FetchEditorURL(r.Context(), buildID); err != nil {
  163. writeJSON(w, http.StatusBadRequest, map[string]any{"error": err.Error()})
  164. return
  165. }
  166. build, err := a.buildSvc.GetBuild(r.Context(), buildID)
  167. if err != nil {
  168. writeJSON(w, http.StatusNotFound, map[string]any{"error": err.Error()})
  169. return
  170. }
  171. writeJSON(w, http.StatusOK, build)
  172. }
  173. func writeJSON(w http.ResponseWriter, status int, v any) {
  174. w.Header().Set("Content-Type", "application/json")
  175. w.WriteHeader(status)
  176. _ = json.NewEncoder(w).Encode(v)
  177. }