Author:
Hash:
Timestamp:
+92 -95 +/-7 browse
Kevin Schoon [me@kevinschoon.com]
1da0aa89a3bb1930d2cd75eb173c2458e7ccd512
Mon, 13 Oct 2025 17:05:45 +0000 (1 month ago)
| 1 | diff --git a/ayllu/src/web2/routes/blob.rs b/ayllu/src/web2/routes/blob.rs |
| 2 | index 800b3b5..8ada1ef 100644 |
| 3 | --- a/ayllu/src/web2/routes/blob.rs |
| 4 | +++ b/ayllu/src/web2/routes/blob.rs |
| 5 | @@ -2,7 +2,7 @@ use askama::Template; |
| 6 | use axum::{ |
| 7 | body::Bytes, |
| 8 | extract::Extension, |
| 9 | - http::{header, HeaderValue}, |
| 10 | + http::{HeaderValue, header}, |
| 11 | response::{Html, IntoResponse, Redirect, Response}, |
| 12 | }; |
| 13 | |
| 14 | @@ -16,10 +16,7 @@ use crate::web2::util; |
| 15 | use crate::{ |
| 16 | config::Config, |
| 17 | languages::Hint, |
| 18 | - web2::{ |
| 19 | - navigation::Items, |
| 20 | - template::{Base, DEFAULT_ANCHOR_SYMBOL}, |
| 21 | - }, |
| 22 | + web2::template::{Base, DEFAULT_ANCHOR_SYMBOL}, |
| 23 | }; |
| 24 | use crate::{ |
| 25 | highlight::{Highlighter, TreeSitterAdapter}, |
| 26 | @@ -31,7 +28,6 @@ use ayllu_git::Wrapper; |
| 27 | #[template(path = "blob.html")] |
| 28 | struct PageTemplate<'a> { |
| 29 | pub base: Base, |
| 30 | - pub subnav_elements: Items, |
| 31 | pub file_name: &'a str, |
| 32 | pub file_size: f64, |
| 33 | pub file_mode_: i32, |
| 34 | @@ -116,6 +112,7 @@ pub async fn serve( |
| 35 | ); |
| 36 | |
| 37 | let raw_url = subnav.get(3).unwrap().1.clone(); |
| 38 | + base.subnav_elements = Some(subnav); |
| 39 | |
| 40 | let file_size = blob.size; |
| 41 | let file_mode = blob.mode; |
| 42 | @@ -125,7 +122,6 @@ pub async fn serve( |
| 43 | Ok(Html( |
| 44 | PageTemplate { |
| 45 | base, |
| 46 | - subnav_elements: subnav, |
| 47 | file_size: (file_size as f64), |
| 48 | file_mode_: file_mode, |
| 49 | file_name: &preamble.file_name(), |
| 50 | diff --git a/ayllu/src/web2/routes/log.rs b/ayllu/src/web2/routes/log.rs |
| 51 | index 4b4d750..9b51b06 100644 |
| 52 | --- a/ayllu/src/web2/routes/log.rs |
| 53 | +++ b/ayllu/src/web2/routes/log.rs |
| 54 | @@ -24,7 +24,6 @@ struct PageTemplate<'a> { |
| 55 | subtitle: &'a str, |
| 56 | file_view: bool, |
| 57 | file_name: &'a str, |
| 58 | - subnav_elements: Items, |
| 59 | commits: Vec<Commit>, |
| 60 | has_more: bool, |
| 61 | last_commit: Option<Commit>, |
| 62 | @@ -40,14 +39,14 @@ pub async fn serve( |
| 63 | let repository = Wrapper::new(preamble.repo_path.as_path())?; |
| 64 | base.nav_elements = |
| 65 | crate::web2::navigation::primary("log", &preamble.collection_name, &preamble.repo_name); |
| 66 | - let subnav_elements = navigation::subnav( |
| 67 | + base.subnav_elements = Some(navigation::subnav( |
| 68 | "log", |
| 69 | &preamble.collection_name, |
| 70 | &preamble.repo_name, |
| 71 | &preamble.file_path_string(), |
| 72 | &preamble.refname, |
| 73 | &preamble.latest_commit_id.clone().unwrap_or(String::new()), |
| 74 | - ); |
| 75 | + )); |
| 76 | let tmpl = match preamble.file_path.as_ref() { |
| 77 | Some(file_path) => { |
| 78 | let title = format!("Log: {}", preamble.file_name()); |
| 79 | @@ -61,7 +60,6 @@ pub async fn serve( |
| 80 | collection: &preamble.collection_name, |
| 81 | subtitle: &title.clone(), |
| 82 | file_view: true, |
| 83 | - subnav_elements, |
| 84 | file_name: &file_path |
| 85 | .file_name() |
| 86 | .map_or(String::default(), |item| item.to_string_lossy().to_string()), |
| 87 | @@ -86,7 +84,6 @@ pub async fn serve( |
| 88 | subtitle: "", |
| 89 | file_name: "", |
| 90 | file_view: false, |
| 91 | - subnav_elements, |
| 92 | has_more: commits.len() == config.items_per_page, |
| 93 | last_commit: commits.last().cloned(), |
| 94 | commits, |
| 95 | diff --git a/ayllu/src/web2/template.rs b/ayllu/src/web2/template.rs |
| 96 | index 7ad648d..60404f3 100644 |
| 97 | --- a/ayllu/src/web2/template.rs |
| 98 | +++ b/ayllu/src/web2/template.rs |
| 99 | @@ -62,6 +62,7 @@ pub struct Base { |
| 100 | pub render_time: Option<String>, |
| 101 | pub current_time: String, |
| 102 | pub nav_elements: Items, |
| 103 | + pub subnav_elements: Option<Items>, |
| 104 | pub logo: String, |
| 105 | pub feed_icon: String, |
| 106 | pub user_config: UserConfig, |
| 107 | @@ -88,6 +89,7 @@ impl Default for Base { |
| 108 | render_time: Default::default(), |
| 109 | current_time: Default::default(), |
| 110 | nav_elements: Default::default(), |
| 111 | + subnav_elements: None, |
| 112 | logo: Default::default(), |
| 113 | feed_icon: Default::default(), |
| 114 | user_config: Default::default(), |
| 115 | diff --git a/ayllu/templates/blob.html b/ayllu/templates/blob.html |
| 116 | index 6483265..c0547f4 100644 |
| 117 | --- a/ayllu/templates/blob.html |
| 118 | +++ b/ayllu/templates/blob.html |
| 119 | @@ -2,7 +2,6 @@ |
| 120 | {% extends "base.html" %} |
| 121 | {% block content %} |
| 122 | <section id="blob" class="raised"> |
| 123 | - {% call macros::navigation(items=subnav_elements, title="Blob") %} |
| 124 | <section class="raised"> |
| 125 | <section class="flex-group info-bar"> |
| 126 | <section class="title"> |
| 127 | diff --git a/ayllu/templates/log.html b/ayllu/templates/log.html |
| 128 | index fb9aab4..058a489 100644 |
| 129 | --- a/ayllu/templates/log.html |
| 130 | +++ b/ayllu/templates/log.html |
| 131 | @@ -2,55 +2,52 @@ |
| 132 | {% extends "base.html" %} |
| 133 | {% block content %} |
| 134 | <section id="log" class="scrollable raised"> |
| 135 | - {% if file_view %} |
| 136 | - {% call macros::navigation(items=subnav_elements, title="Log") %} |
| 137 | - {% endif %} |
| 138 | - <section class="info-bar"> |
| 139 | - <section class="title"> |
| 140 | - Log |
| 141 | - </section> |
| 142 | + <section class="info-bar"> |
| 143 | + <section class="title"> |
| 144 | + Log |
| 145 | </section> |
| 146 | - <section class="lower-half"> |
| 147 | - <table class="data-table"> |
| 148 | - <thead> |
| 149 | + </section> |
| 150 | + <section class="lower-half"> |
| 151 | + <table class="data-table"> |
| 152 | + <thead> |
| 153 | + <tr> |
| 154 | + <th>ID</th> |
| 155 | + <th>Flags</th> |
| 156 | + <th>Age</th> |
| 157 | + <th>Author</th> |
| 158 | + <th>Message</th> |
| 159 | + </tr> |
| 160 | + </thead> |
| 161 | + <tbody> |
| 162 | + {% for commit in commits %} |
| 163 | <tr> |
| 164 | - <th>ID</th> |
| 165 | - <th>Flags</th> |
| 166 | - <th>Age</th> |
| 167 | - <th>Author</th> |
| 168 | - <th>Message</th> |
| 169 | + <td> |
| 170 | + <span class="{%- if let Some(_) = commit.is_verified -%}positive{%- else -%}negative {%- endif -%}"> |
| 171 | + <a href="/{{ collection }}/{{ name }}/commit/{{ commit.id }}">{{ commit.id | truncate(12) }}</a> |
| 172 | + </span> |
| 173 | + </td> |
| 174 | + <td> |
| 175 | + {% if let Some(has_note) = commit.has_note %} |
| 176 | + {% if has_note %}<div data-tooltip="Note">[N]</div>{% endif %} |
| 177 | + {% endif %} |
| 178 | + {% if commit.is_extended %}<div data-tooltip="Extended Commit">[E]</div>{% endif %} |
| 179 | + </td> |
| 180 | + <td>{{ commit.epoch | friendly_time }}</td> |
| 181 | + <td> |
| 182 | + <a href="/{{ collection }}/{{ name }}/log?username={{ commit.author_name | urlencode }}&email={{ commit.author_email | urlencode }}">{{ commit.author_name }}</a> |
| 183 | + </td> |
| 184 | + <td>{{ commit.summary | truncate(85) }}</td> |
| 185 | </tr> |
| 186 | - </thead> |
| 187 | - <tbody> |
| 188 | - {% for commit in commits %} |
| 189 | - <tr> |
| 190 | - <td> |
| 191 | - <span class="{%- if let Some(_) = commit.is_verified -%}positive{%- else -%}negative {%- endif -%}"> |
| 192 | - <a href="/{{ collection }}/{{ name }}/commit/{{ commit.id }}">{{ commit.id | truncate(12) }}</a> |
| 193 | - </span> |
| 194 | - </td> |
| 195 | - <td> |
| 196 | - {% if let Some(has_note) = commit.has_note %} |
| 197 | - {% if has_note %}<div data-tooltip="Note">[N]</div>{% endif %} |
| 198 | - {% endif %} |
| 199 | - {% if commit.is_extended %}<div data-tooltip="Extended Commit">[E]</div>{% endif %} |
| 200 | - </td> |
| 201 | - <td>{{ commit.epoch | friendly_time }}</td> |
| 202 | - <td> |
| 203 | - <a href="/{{ collection }}/{{ name }}/log?username={{ commit.author_name | urlencode }}&email={{ commit.author_email | urlencode }}">{{ commit.author_name }}</a> |
| 204 | - </td> |
| 205 | - <td>{{ commit.summary | truncate(85) }}</td> |
| 206 | - </tr> |
| 207 | - {% endfor %} |
| 208 | - </tbody> |
| 209 | - </table> |
| 210 | - {% if has_more -%} |
| 211 | - <footer class="pagination"> |
| 212 | - {%- if let Some(last_commit) = last_commit -%} |
| 213 | - <span class="right"><a href="/{{ collection }}/{{ name }}/log/{{ last_commit.id }}"><b>next</b></a></span> |
| 214 | - {%- endif -%} |
| 215 | - </footer> |
| 216 | - {% endif %} |
| 217 | - </section> |
| 218 | + {% endfor %} |
| 219 | + </tbody> |
| 220 | + </table> |
| 221 | + {% if has_more -%} |
| 222 | + <footer class="pagination"> |
| 223 | + {%- if let Some(last_commit) = last_commit -%} |
| 224 | + <span class="right"><a href="/{{ collection }}/{{ name }}/log/{{ last_commit.id }}"><b>next</b></a></span> |
| 225 | + {%- endif -%} |
| 226 | + </footer> |
| 227 | + {% endif %} |
| 228 | </section> |
| 229 | + </section> |
| 230 | {% endblock %} |
| 231 | diff --git a/ayllu/templates/nav.html b/ayllu/templates/nav.html |
| 232 | index 79b390f..f3020d0 100644 |
| 233 | --- a/ayllu/templates/nav.html |
| 234 | +++ b/ayllu/templates/nav.html |
| 235 | @@ -1,26 +1,21 @@ |
| 236 | + <input id="panel-toggle" type="checkbox" name="menu" {%- if base.menu_open %} checked {%- endif %} /> |
| 237 | <nav> |
| 238 | - <input id="panel-toggle" type="checkbox" name="menu" {%- if base.menu_open %} checked {%- endif %} /> |
| 239 | - <div class="group"> |
| 240 | - <div id="left"> |
| 241 | - <ul class="outer"> |
| 242 | - <li class="tilde"><a href="/">~</a></li> |
| 243 | - <li><a href="/about">About</a></li> |
| 244 | - <li> |
| 245 | - <label for="panel-toggle">Config</label> |
| 246 | - </li> |
| 247 | - </ul> |
| 248 | - </div> |
| 249 | - <div id="right"> |
| 250 | - <ul class="outer"> |
| 251 | - {% for item in base.nav_elements %} |
| 252 | - <li {% if item.2 %}class="active"{% endif %}> |
| 253 | - <a href="{{ item.1 }}">{{ item.0 }}</a> |
| 254 | - </li> |
| 255 | - {% endfor %} |
| 256 | - </ul> |
| 257 | - </div> |
| 258 | - </div> |
| 259 | - <div id="control-panel"> |
| 260 | + <ul> |
| 261 | + <li class="tilde"><a href="/">~</a></li> |
| 262 | + <li><a href="/about">About</a></li> |
| 263 | + <li> |
| 264 | + <label for="panel-toggle">Config</label> |
| 265 | + </li> |
| 266 | + </ul> |
| 267 | + <ul> |
| 268 | + {% for item in base.nav_elements %} |
| 269 | + <li {% if item.2 %}class="active"{% endif %}> |
| 270 | + <a href="{{ item.1 }}">{{ item.0 }}</a> |
| 271 | + </li> |
| 272 | + {% endfor %} |
| 273 | + </ul> |
| 274 | + </nav> |
| 275 | + <div id="control-panel"> |
| 276 | <form action="/config" method="post"> |
| 277 | <label for="theme">items-per-page</label> |
| 278 | <select id="items_per_page" name="items_per_page" required> |
| 279 | @@ -56,6 +51,17 @@ |
| 280 | <input id="current_url" name="current_url" type="text" value="{{base.path}}"/> |
| 281 | <button type="submit">Submit</button> |
| 282 | </form> |
| 283 | - |
| 284 | - </div> |
| 285 | + </div> |
| 286 | + {%- if let Some(subnav) = base.subnav_elements -%} |
| 287 | + <nav class="subnav"> |
| 288 | + <ul></ul> |
| 289 | + <ul> |
| 290 | + {% for item in subnav %} |
| 291 | + <li {% if item.2 %}class="active"{% endif %}> |
| 292 | + <a href="{{ item.1 }}">{{ item.0 }}</a> |
| 293 | + </li> |
| 294 | + {% endfor %} |
| 295 | + </ul> |
| 296 | </nav> |
| 297 | + {%- endif -%} |
| 298 | + |
| 299 | diff --git a/ayllu/themes/base.css b/ayllu/themes/base.css |
| 300 | index 125df04..367c4be 100644 |
| 301 | --- a/ayllu/themes/base.css |
| 302 | +++ b/ayllu/themes/base.css |
| 303 | @@ -54,28 +54,28 @@ table { |
| 304 | |
| 305 | nav { |
| 306 | border: solid 2px; |
| 307 | - } |
| 308 | |
| 309 | - nav div.group { |
| 310 | + text-decoration: none; |
| 311 | + |
| 312 | display: flex; |
| 313 | + flex-direction: row; |
| 314 | justify-content: space-between; |
| 315 | |
| 316 | - ul.outer { |
| 317 | - list-style-type: none; |
| 318 | - margin: 0; |
| 319 | + ul { |
| 320 | + list-style-type: none; margin: 0; |
| 321 | padding: 0; |
| 322 | display: flex; |
| 323 | |
| 324 | li { |
| 325 | margin: 5px; |
| 326 | + |
| 327 | + a { |
| 328 | + text-decoration: none; |
| 329 | + } |
| 330 | } |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | - nav ul li a { |
| 335 | - text-decoration: none; |
| 336 | - } |
| 337 | - |
| 338 | div#control-panel { |
| 339 | display: none; |
| 340 | padding: .5em; |
| 341 | @@ -87,7 +87,7 @@ ul.submenu { |
| 342 | } |
| 343 | |
| 344 | input:checked~div#control-panel { |
| 345 | - display: block; |
| 346 | + display: flex; |
| 347 | } |
| 348 | |
| 349 | input:checked~ul.submenu { |
| 350 | @@ -431,4 +431,4 @@ li.active { |
| 351 | width: 100%; |
| 352 | height: auto; |
| 353 | } |
| 354 | - } |
| 355 | \ No newline at end of file |
| 356 | + } |