feat: add PATCH /tags/{id}/rules/{then_id} to activate/deactivate rules

- openapi.yaml: new PATCH endpoint with is_active body, returns TagRule
- backend/service: SetRuleActive calls repo.SetActive then returns updated rule
- backend/handler: PatchRule validates body and delegates to service
- backend/router: register PATCH /:tag_id/rules/:then_tag_id
- frontend: TagRuleEditor uses PATCH instead of delete+recreate
- mock: handle PATCH /tags/{id}/rules/{then_id}

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-05 23:31:12 +03:00
parent 871250345a
commit 21f3acadf0
6 changed files with 97 additions and 6 deletions
+1
View File
@@ -93,6 +93,7 @@ func NewRouter(
tags.GET("/:tag_id/rules", tagHandler.ListRules)
tags.POST("/:tag_id/rules", tagHandler.CreateRule)
tags.PATCH("/:tag_id/rules/:then_tag_id", tagHandler.PatchRule)
tags.DELETE("/:tag_id/rules/:then_tag_id", tagHandler.DeleteRule)
}
+33
View File
@@ -354,6 +354,39 @@ func (h *TagHandler) CreateRule(c *gin.Context) {
respondJSON(c, http.StatusCreated, toTagRuleJSON(*rule))
}
// ---------------------------------------------------------------------------
// PATCH /tags/:tag_id/rules/:then_tag_id
// ---------------------------------------------------------------------------
func (h *TagHandler) PatchRule(c *gin.Context) {
whenTagID, ok := parseTagID(c)
if !ok {
return
}
thenTagID, err := uuid.Parse(c.Param("then_tag_id"))
if err != nil {
respondError(c, domain.ErrValidation)
return
}
var body struct {
IsActive *bool `json:"is_active"`
}
if err := c.ShouldBindJSON(&body); err != nil || body.IsActive == nil {
respondError(c, domain.ErrValidation)
return
}
rule, err := h.tagSvc.SetRuleActive(c.Request.Context(), whenTagID, thenTagID, *body.IsActive)
if err != nil {
respondError(c, err)
return
}
respondJSON(c, http.StatusOK, toTagRuleJSON(*rule))
}
// ---------------------------------------------------------------------------
// DELETE /tags/:tag_id/rules/:then_tag_id
// ---------------------------------------------------------------------------