Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Build out change review and threaded discussions

f6f4b1db24292d1df877680714952a9c568e2b78 · Keenan Nemetz · 15d ago · parent 564acd4b

Build out change review and threaded discussions

- Add Conversation, Files and Runs tabs to change requests. Files uses the
  code-browser shape with a changed-file tree and one selected-file diff;
  Runs lists the head commit's workflow results.
- Show anchored review comments beneath the line, with a collapsed excerpt
  read from the exact blob that was reviewed, and return posted anchors to
  their line note.
- Add comment threads: any comment can be replied to, the UI flattens the
  descendants under one root, reply context links back to the parent, and
  reply targets feed a single composer at the foot of the discussion.
- Collapse reply groups while keeping the root visible, and scroll to the
  composer when Reply is selected.
- Add comment context menus with Reply, Copy text, Copy link, Edit and
  Delete. Add web edit/delete routes with author or admin checks; deletion
  leaves a tombstone so replies keep their thread.
- Support --reply-to in the issue and change CLI commands, and treat a
  missing parent as a tombstone rather than an invalid tree.
- Fix the diff comment gutter, action button colours, reply labels, and
  keep the Files tree and diff pane aligned.

Update metadata validation, web templates, CSS, JavaScript, tests, and the
CLI/change-request/issue docs.

server/server.go +8

@@ -177,6 +177,8 @@ func (s *Server) routes() *http.ServeMux {
177 177 mux.HandleFunc("POST /r/{name}/issues", w.CreateIssue)
178 178 mux.HandleFunc("GET /r/{name}/issues/{id}", w.IssueView)
179 179 mux.HandleFunc("POST /r/{name}/issues/{id}/comments", w.AddIssueComment)
180 mux.HandleFunc("POST /r/{name}/issues/{id}/comments/{comment}/edit", w.EditIssueComment)
181 mux.HandleFunc("POST /r/{name}/issues/{id}/comments/{comment}/delete", w.DeleteIssueComment)
180 182 mux.HandleFunc("POST /r/{name}/issues/{id}/state", w.ChangeIssueState)
181 183 mux.HandleFunc("POST /r/{name}/issues/{id}/labels", w.SetIssueLabels)
182 184 mux.HandleFunc("POST /r/{name}/issues/{id}/assignees", w.SetIssueAssignees)
@@ -184,8 +186,14 @@ func (s *Server) routes() *http.ServeMux {
184 186 mux.HandleFunc("GET /r/{name}/requests/new", w.NewChangePage)
185 187 mux.HandleFunc("POST /r/{name}/requests", w.CreateChangeRequest)
186 188 mux.HandleFunc("GET /r/{name}/requests/{id}", w.RequestView)
189 mux.HandleFunc("GET /r/{name}/requests/{id}/files", w.RequestFiles)
190 mux.HandleFunc("GET /r/{name}/requests/{id}/files/{path...}", w.RequestFiles)
191 mux.HandleFunc("GET /r/{name}/requests/{id}/runs", w.RequestRuns)
192 mux.HandleFunc("GET /r/{name}/requests/{id}/comment-form", w.RequestCommentForm)
187 193 mux.HandleFunc("POST /r/{name}/requests/{id}/approve", w.ApproveRequest)
188 194 mux.HandleFunc("POST /r/{name}/requests/{id}/comments", w.AddRequestComment)
195 mux.HandleFunc("POST /r/{name}/requests/{id}/comments/{comment}/edit", w.EditRequestComment)
196 mux.HandleFunc("POST /r/{name}/requests/{id}/comments/{comment}/delete", w.DeleteRequestComment)
189 197 mux.HandleFunc("POST /r/{name}/requests/{id}/state", w.ChangeRequestState)
190 198 mux.HandleFunc("POST /r/{name}/ci/allow", w.AllowContributorCI)
191 199 // A tag may contain "/", so the detail route takes the rest of the path; the