Skip to content

Commit ace82fa

Browse files
Load release list only when needed
1 parent 77eaf07 commit ace82fa

File tree

6 files changed

+105
-5
lines changed

6 files changed

+105
-5
lines changed

src/web/crate_details.rs

+47
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,53 @@ pub(crate) async fn crate_details_handler(
373373
Ok(res.into_response())
374374
}
375375

376+
#[derive(Debug, Clone, PartialEq, Serialize)]
377+
struct ReleaseList {
378+
releases: Vec<Release>,
379+
crate_name: String,
380+
}
381+
382+
impl_axum_webpage! {
383+
ReleaseList = "rustdoc/releases.html",
384+
cpu_intensive_rendering = true,
385+
}
386+
387+
#[tracing::instrument]
388+
pub(crate) async fn get_all_releases(
389+
Path(params): Path<CrateDetailHandlerParams>,
390+
Extension(pool): Extension<Pool>,
391+
) -> AxumResult<AxumResponse> {
392+
let releases: Vec<Release> = spawn_blocking({
393+
let pool = pool.clone();
394+
let params = params.clone();
395+
move || {
396+
let mut conn = pool.get()?;
397+
let query = "
398+
SELECT
399+
crates.id AS crate_id
400+
FROM crates
401+
WHERE crates.name = $1;";
402+
403+
let rows = conn.query(query, &[&params.name])?;
404+
405+
let result = if rows.is_empty() {
406+
return Ok(Vec::new());
407+
} else {
408+
&rows[0]
409+
};
410+
// get releases, sorted by semver
411+
releases_for_crate(&mut *conn, result.get("crate_id"))
412+
}
413+
})
414+
.await?;
415+
416+
let res = ReleaseList {
417+
releases,
418+
crate_name: params.name,
419+
};
420+
Ok(res.into_response())
421+
}
422+
376423
#[cfg(test)]
377424
mod tests {
378425
use super::*;

src/web/routes.rs

+4
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ pub(super) fn build_axum_routes() -> AxumRouter {
167167
"/crate/:name",
168168
get_internal(super::crate_details::crate_details_handler),
169169
)
170+
.route(
171+
"/:name/releases",
172+
get_internal(super::crate_details::get_all_releases),
173+
)
170174
.route_with_tsr(
171175
"/crate/:name/:version",
172176
get_internal(super::crate_details::crate_details_handler),

static/menu.js

+29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,34 @@ const updateMenuPositionForSubMenu = (currentMenuSupplier) => {
55
subMenu?.style.setProperty('--menu-x', `${currentMenu.getBoundingClientRect().x}px`);
66
}
77

8+
function generateReleaseList(data, crateName) {
9+
}
10+
11+
let loadReleases = function() {
12+
const releaseListElem = document.getElementById('releases-list');
13+
// To prevent reloading the list unnecessarily.
14+
loadReleases = function() {};
15+
if (!releaseListElem) {
16+
// We're not in a documentation page, so no need to do anything.
17+
return;
18+
}
19+
const crateName = window.location.pathname.split('/')[1];
20+
const xhttp = new XMLHttpRequest();
21+
xhttp.onreadystatechange = function() {
22+
if (xhttp.readyState !== XMLHttpRequest.DONE) {
23+
return;
24+
}
25+
if (xhttp.status === 200) {
26+
releaseListElem.innerHTML = xhttp.responseText;
27+
} else {
28+
console.error(`Failed to load release list: [${xhttp.status}] ${xhttp.responseText}`);
29+
document.getElementById('releases-list').innerHTML = "Failed to load release list";
30+
}
31+
};
32+
xhttp.open("GET", `/${crateName}/releases`, true);
33+
xhttp.send();
34+
};
35+
836
// Allow menus to be open and used by keyboard.
937
(function() {
1038
var currentMenu;
@@ -53,6 +81,7 @@ const updateMenuPositionForSubMenu = (currentMenuSupplier) => {
5381
currentMenu = newMenu;
5482
newMenu.className += " pure-menu-active";
5583
backdrop.style.display = "block";
84+
loadReleases();
5685
}
5786
function menuOnClick(e) {
5887
if (this.getAttribute("href") != "#") {

templates/rustdoc/releases.html

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{% import "macros.html" as macros %}
2+
{% set target = "" %}
3+
{% set inner_path = releases[0].target_name ~ "/index.html" %}
4+
<ul class="pure-menu-list">
5+
{{ macros::releases_list(name=crate_name, releases=releases, target=target, inner_path=inner_path) }}
6+
</ul>

templates/rustdoc/topbar.html

+2-5
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,8 @@
134134
<li class="pure-menu-heading">Versions</li>
135135

136136
<li class="pure-menu-item">
137-
<div class="pure-menu pure-menu-scrollable sub-menu" tabindex="-1">
138-
<ul class="pure-menu-list">
139-
{# Display all releases of this crate #}
140-
{{ macros::releases_list(name=krate.name, releases=krate.releases, target=target, inner_path=inner_path) }}
141-
</ul>
137+
<div class="pure-menu pure-menu-scrollable sub-menu" id="releases-list" tabindex="-1">
138+
<span class="rotate">{{ "spinner" | fas }}</span>
142139
</div>
143140
</li>
144141
</ul>

templates/style/_navbar.scss

+17
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ body {
1515
padding: 0;
1616
}
1717

18+
@keyframes rotating_text {
19+
from {
20+
transform: rotate(0deg);
21+
}
22+
to {
23+
transform: rotate(360deg);
24+
}
25+
}
26+
1827
div.nav-container {
1928
// Nothing is supposed to be over or hovering the top navbar. Maybe add a few others '('? :)
2029
z-index: 999;
@@ -324,6 +333,14 @@ div.nav-container {
324333
}
325334
}
326335
}
336+
337+
#releases-list {
338+
.rotate {
339+
display: inline-block;
340+
font-size: 30px;
341+
animation: rotating_text 2s linear infinite;
342+
}
343+
}
327344
}
328345

329346
#nav-search {

0 commit comments

Comments
 (0)