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.
Update the change page as live regions, not one sidebar swap
707dfd10f309461a77a4a8f73dcce74b07c91fd6 · Keenan Nemetz · 10d ago · parent 9f5efa3c
Update the change page as live regions, not one sidebar swap The 20-second poll replaced the entire sidebar, so every new widget needed its own reason to opt out and live updates stopped while it was in use. The sidebar is now a set of regions: review status, changes, approvals, checks, and the combined result are data-only live regions returned with hx-swap-oob; the target picker, issue search, and composers are outside every polled swap. Approval and the other multi-region writes use the same out-of-band group, and the page action group refreshes from the write without replacing unrelated state.
docs/ui-plan.md +25−2
| @@ -185,8 +185,11 @@ every page. Interactions are converted one flow at a time: | |||
| 185 | 185 | - done — issue close/reopen, labels, assignees, and comments update their | |
| 186 | 186 | section in place. Labels and assignees save on token change; there is no | |
| 187 | 187 | visible save button. | |
| 188 | - done — change approval updates the sidebar, comments update the discussion | ||
| 189 | fragment, and close/reopen are page actions. | ||
| 188 | - done — change approval updates the live status regions and the page actions, | ||
| 189 | comments update the discussion fragment, and close/reopen are page actions. | ||
| 190 | - done — the change page polls one live endpoint that returns out-of-band | ||
| 191 | updates for the status regions; the target picker, issue search, and | ||
| 192 | discussion are outside that swap. | ||
| 190 | 193 | - done — the change Issues section links and unlinks issues in place. | |
| 191 | 194 | - done — Issues and Change requests filters swap their list fragment and push the URL. | |
| 192 | 195 | - done — repository activity feed swaps its event fragment for type filters and | |
| @@ -201,6 +204,26 @@ every page. Interactions are converted one flow at a time: | |||
| 201 | 204 | The token input and passkey ceremonies stay custom JavaScript: HTMX moves HTML | |
| 202 | 205 | from the server, it does not manage client-side chip state or credential APIs. | |
| 203 | 206 | ||
| 207 | ### Dynamic regions | ||
| 208 | |||
| 209 | Every dynamic area is one of two kinds. A **state region** holds a form, input, | ||
| 210 | open popover, or editor and is replaced only by the action that owns it. A | ||
| 211 | **live region** is read-only status or data and may be refreshed in the | ||
| 212 | background. A poll response may contain live regions only; if a widget needs | ||
| 213 | both, its data child is a separate live region and its controls are left alone. | ||
| 214 | |||
| 215 | The change sidebar follows this split. `GET /r/{name}/requests/{id}/live` | ||
| 216 | returns `request-review-status`, `request-changes`, `request-approvals`, | ||
| 217 | `request-checks`, `request-combined`, and `request-merge-note` with | ||
| 218 | `hx-swap-oob="outerHTML"`. The poll element itself uses `hx-swap="none"`, so the | ||
| 219 | target picker, issue search, and comment composers keep their state while the | ||
| 220 | status updates. Write responses use the same out-of-band group when they change | ||
| 221 | more than one live region, or target one state region directly when the write | ||
| 222 | belongs to that widget. The page action group is updated by writes, not by the | ||
| 223 | poll, so a poll never replaces a form. Trigger | ||
| 224 | conditions are for visibility and throttling, not for pausing a poll because a | ||
| 225 | widget happens to be open. | ||
| 226 | |||
| 204 | 227 | ## Activity feed | |
| 205 | 228 | ||
| 206 | 229 | No notification table and no per-account inbox. The feed is derived from Git, the | |