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.
Search every issue, change and comment from the top bar
6c03e6d3243d31a82210cc7bc689ab3e28226b6c · Keenan Nemetz · 10d ago · parent 389317ee
Search every issue, change and comment from the top bar The top bar's search now opens a command palette instead of a text field. The dialog asks the same index and visibility rule as /search, so private repositories stay out, and it answers with a short list plus a link to the full results. A button that looks like the old input launches it, labelled with the platform's shortcut; Ctrl K or Cmd K works anywhere. The bar's contents also line up with the page column now, and Home is marked current only on the landing page rather than on every repository page.
server/web/templates/chrome.html +30−4
| @@ -27,14 +27,17 @@ | |||
| 27 | 27 | <header class="topbar"> | |
| 28 | 28 | <a class="brand" href="/" aria-label="Vole home"><span class="mark" aria-hidden="true"></span></a> | |
| 29 | 29 | <nav class="topnav" aria-label="Global"> | |
| 30 | <a class="{{if eq .Section "repos"}}active{{end}}" href="/"{{if eq .Section "repos"}} aria-current="page"{{end}}>{{icon "house"}}Home</a> | ||
| 30 | <a class="{{if eq .Section "home"}}active{{end}}" href="/"{{if eq .Section "home"}} aria-current="page"{{end}}>{{icon "house"}}Home</a> | ||
| 31 | 31 | <a class="{{if eq .Section "activity"}}active{{end}}" href="/activity"{{if eq .Section "activity"}} aria-current="page"{{end}}>{{icon "activity"}}Activity</a> | |
| 32 | 32 | <a class="{{if eq .Section "search"}}active{{end}}" href="/search"{{if eq .Section "search"}} aria-current="page"{{end}}>{{icon "search"}}Search</a> | |
| 33 | 33 | {{if .InstanceAdmin}}<a class="{{if eq .Section "users"}}active{{end}}" href="/users"{{if eq .Section "users"}} aria-current="page"{{end}}>{{icon "users"}}Accounts</a>{{end}} | |
| 34 | 34 | </nav> | |
| 35 | <form class="topsearch" method="get" action="/" role="search"> | ||
| 36 | <input type="search" name="q" value="{{.Query}}" placeholder="Search repositories" aria-label="Search repositories"> | ||
| 37 | <button type="submit" aria-label="Search repositories">{{icon "search"}}</button> | ||
| 35 | <form class="topsearch" method="get" action="/search" role="search"> | ||
| 36 | <button type="submit" class="topsearch-box" data-palette-open aria-haspopup="dialog" aria-controls="search-palette" aria-keyshortcuts="Control+K Meta+K"> | ||
| 37 | {{icon "search"}} | ||
| 38 | <span class="topsearch-label">Search issues, changes, comments</span> | ||
| 39 | <kbd class="topsearch-key" data-palette-key aria-hidden="true">Ctrl K</kbd> | ||
| 40 | </button> | ||
| 38 | 41 | </form> | |
| 39 | 42 | <div class="topright"> | |
| 40 | 43 | {{if .LoggedIn}} | |
| @@ -57,6 +60,29 @@ | |||
| 57 | 60 | {{end}} | |
| 58 | 61 | </div> | |
| 59 | 62 | </header> | |
| 63 | {{/* The global search is also a command palette: one field over every issue, | ||
| 64 | change request and comment the reader can see. Without JavaScript the top | ||
| 65 | bar's form still submits to /search; the dialog is the enhancement. */}} | ||
| 66 | <dialog class="palette" id="search-palette" aria-label="Search issues, changes and comments"> | ||
| 67 | <form class="palette-search" method="get" action="/search" role="search" | ||
| 68 | hx-get="/search/palette" hx-trigger="input changed delay:250ms, search" | ||
| 69 | hx-target="#palette-results" hx-swap="innerHTML" hx-sync="this:replace"> | ||
| 70 | <span aria-hidden="true">{{icon "search"}}</span> | ||
| 71 | <input type="search" name="q" id="search-palette-input" | ||
| 72 | placeholder="Search issues, changes and comments" | ||
| 73 | aria-label="Search issues, changes and comments" autocomplete="off" | ||
| 74 | role="combobox" aria-expanded="true" aria-controls="palette-results" aria-autocomplete="list"> | ||
| 75 | <button type="button" class="palette-close" data-palette-close aria-label="Close search">{{icon "x"}}</button> | ||
| 76 | </form> | ||
| 77 | <div class="palette-results" id="palette-results" role="listbox" aria-label="Search results"> | ||
| 78 | {{template "palette_hint"}} | ||
| 79 | </div> | ||
| 80 | <div class="palette-foot" aria-hidden="true"> | ||
| 81 | <span><kbd>↑</kbd> <kbd>↓</kbd> move</span> | ||
| 82 | <span><kbd>Enter</kbd> open</span> | ||
| 83 | <span><kbd>Esc</kbd> close</span> | ||
| 84 | </div> | ||
| 85 | </dialog> | ||
| 60 | 86 | <a class="skip-link" href="#main">Skip to content</a> | |
| 61 | 87 | <main class="page" id="main"> | |
| 62 | 88 | {{if .Error}}<div class="flash bad">{{.Error}}</div>{{end}} | |