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/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software: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/web/web.go +19−18

@@ -67,24 +67,25 @@ func New(repos *repo.Store, ix *index.Store, ident *identity.Store, rs *runs.Sto
67 67 // below can be a method: metadata files carry account names and approvals are
68 68 // keyed by ids, and a page should show the display label for either.
69 69 w.Tmpl, err = template.New("vole").Funcs(template.FuncMap{
70 "since": humanSince,
71 "short": format.SHA,
72 "esc": url.PathEscape,
73 "bytes": format.Bytes,
74 "credid": identity.CredentialIDString,
75 "who": w.who,
76 "nav": w.repoNav,
77 "inc": func(i int) int { return i + 1 },
78 "initial": initial,
79 "tone": tone,
80 "urlquery": url.QueryEscape,
81 "join": strings.Join,
82 "tokenPicker": tokenPicker,
83 "icon": icon,
84 "treeContext": treeContext,
85 "pathurl": pathURL,
86 "pathjoin": joinPath,
87 "parentpath": parentPath,
70 "since": humanSince,
71 "short": format.SHA,
72 "esc": url.PathEscape,
73 "bytes": format.Bytes,
74 "credid": identity.CredentialIDString,
75 "who": w.who,
76 "nav": w.repoNav,
77 "inc": func(i int) int { return i + 1 },
78 "initial": initial,
79 "tone": tone,
80 "urlquery": url.QueryEscape,
81 "join": strings.Join,
82 "tokenPicker": tokenPicker,
83 "icon": icon,
84 "treeContext": treeContext,
85 "reviewTreeContext": reviewTreeContext,
86 "pathurl": pathURL,
87 "pathjoin": joinPath,
88 "parentpath": parentPath,
88 89 }).ParseFS(templateFS, "templates/*.html")
89 90 if err != nil {
90 91 return nil, err