1 Commits

Author SHA1 Message Date
Forbes
7d4e6fb099 feat(api): allow revision comment editing after creation
Add comment field to UpdateRevisionRequest and extend UpdateRevisionStatus
to accept an optional comment parameter. The PATCH /api/items/{partNumber}/revisions/{revision}
endpoint now accepts a comment field alongside status and labels.

Closes #174
2026-03-04 14:27:32 -06:00
4 changed files with 42 additions and 10 deletions

View File

@@ -1058,10 +1058,11 @@ type RevisionDiffResponse struct {
Changed map[string]db.PropertyChange `json:"changed,omitempty"`
}
// UpdateRevisionRequest represents a request to update revision status/labels.
// UpdateRevisionRequest represents a request to update revision status/labels/comment.
type UpdateRevisionRequest struct {
Status *string `json:"status,omitempty"`
Labels []string `json:"labels,omitempty"`
Status *string `json:"status,omitempty"`
Labels []string `json:"labels,omitempty"`
Comment *string `json:"comment,omitempty"`
}
// RollbackRequest represents a request to rollback to a previous revision.
@@ -1164,12 +1165,12 @@ func (s *Server) HandleUpdateRevision(w http.ResponseWriter, r *http.Request) {
}
// Validate that at least one field is being updated
if req.Status == nil && req.Labels == nil {
writeError(w, http.StatusBadRequest, "invalid_request", "Must provide status or labels to update")
if req.Status == nil && req.Labels == nil && req.Comment == nil {
writeError(w, http.StatusBadRequest, "invalid_request", "Must provide status, labels, or comment to update")
return
}
err = s.items.UpdateRevisionStatus(ctx, item.ID, revNum, req.Status, req.Labels)
err = s.items.UpdateRevisionStatus(ctx, item.ID, revNum, req.Status, req.Labels, req.Comment)
if err != nil {
if err.Error() == "revision not found" {
writeError(w, http.StatusNotFound, "not_found", "Revision not found")

View File

@@ -150,6 +150,31 @@ func TestHandleUpdateRevision(t *testing.T) {
}
}
func TestHandleUpdateRevisionComment(t *testing.T) {
s := newTestServer(t)
router := newRevisionRouter(s)
createItemDirect(t, s, "REVCMT-001", "update comment", nil)
body := `{"comment":"updated comment"}`
req := authRequest(httptest.NewRequest("PATCH", "/api/items/REVCMT-001/revisions/1", strings.NewReader(body)))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("status: got %d, want %d; body: %s", w.Code, http.StatusOK, w.Body.String())
}
var rev RevisionResponse
if err := json.Unmarshal(w.Body.Bytes(), &rev); err != nil {
t.Fatalf("decoding response: %v", err)
}
if rev.Comment == nil || *rev.Comment != "updated comment" {
t.Errorf("comment: got %v, want %q", rev.Comment, "updated comment")
}
}
func TestHandleCompareRevisions(t *testing.T) {
s := newTestServer(t)
router := newRevisionRouter(s)

View File

@@ -491,8 +491,8 @@ func (r *ItemRepository) GetRevision(ctx context.Context, itemID string, revisio
}
// UpdateRevisionStatus updates the status and/or labels of a revision.
func (r *ItemRepository) UpdateRevisionStatus(ctx context.Context, itemID string, revisionNumber int, status *string, labels []string) error {
if status == nil && labels == nil {
func (r *ItemRepository) UpdateRevisionStatus(ctx context.Context, itemID string, revisionNumber int, status *string, labels []string, comment *string) error {
if status == nil && labels == nil && comment == nil {
return nil // Nothing to update
}
@@ -524,6 +524,12 @@ func (r *ItemRepository) UpdateRevisionStatus(ctx context.Context, itemID string
argNum++
}
if comment != nil {
updates = append(updates, fmt.Sprintf("comment = $%d", argNum))
args = append(args, *comment)
argNum++
}
query += updates[0]
for i := 1; i < len(updates); i++ {
query += ", " + updates[i]

View File

@@ -105,7 +105,7 @@ func TestRevisionStatusUpdate(t *testing.T) {
}
status := "released"
if err := repo.UpdateRevisionStatus(ctx, item.ID, 1, &status, nil); err != nil {
if err := repo.UpdateRevisionStatus(ctx, item.ID, 1, &status, nil, nil); err != nil {
t.Fatalf("UpdateRevisionStatus: %v", err)
}
@@ -129,7 +129,7 @@ func TestRevisionLabelsUpdate(t *testing.T) {
}
labels := []string{"prototype", "urgent"}
if err := repo.UpdateRevisionStatus(ctx, item.ID, 1, nil, labels); err != nil {
if err := repo.UpdateRevisionStatus(ctx, item.ID, 1, nil, labels, nil); err != nil {
t.Fatalf("UpdateRevisionStatus: %v", err)
}