Render no breadcrumbs and highlight no site tree node on auxiliary pages

This commit is contained in:
Simon Repp
2024-04-20 23:42:41 +02:00
parent d88ac25aac
commit 8e77ad7204
5 changed files with 70 additions and 53 deletions
+1 -1
View File
@@ -415,7 +415,7 @@ pub fn edit_page(
let site = context.get_site();
let head_title = collection.title.as_deref().unwrap_or_else(|| collection.slug());
let html = layout(context, path, &site, &body, head_title);
let html = layout(context, Some(path), &site, &body, head_title);
HttpResponse::Ok()
.content_type(ContentType::html())
+12 -14
View File
@@ -124,7 +124,7 @@ pub async fn index(context: Data<Arc<Context>>) -> HttpResponse {
}
}
let html = layout(&context, "", &site, &body, site.title());
let html = layout(&context, None, &site, &body, site.title());
HttpResponse::Ok()
.content_type(ContentType::html())
@@ -237,19 +237,17 @@ fn storage_stats_html(context: &Context, videos: &Vec<Arc<Video>>) -> String {
let total_size_human = human_size(total_size);
formatdoc!(r#"
<div class="form_group">
<svg class="storage_graph" width="{diameter}" height="{diameter}" version="1.1" viewBox="0 0 {diameter} {diameter}" xmlns="http://www.w3.org/2000/svg">
<g transform="scale(-1,1)" transform-origin="{radius} {radius}">
{slices}
</g>
<text text-anchor="middle" x="{radius}" y="{radius}">
{total_size_human}
</text>
</svg>
<svg class="storage_graph" width="{diameter}" height="{diameter}" version="1.1" viewBox="0 0 {diameter} {diameter}" xmlns="http://www.w3.org/2000/svg">
<g transform="scale(-1,1)" transform-origin="{radius} {radius}">
{slices}
</g>
<text text-anchor="middle" x="{radius}" y="{radius}">
{total_size_human}
</text>
</svg>
<ul class="storage_legend">
{list}
</ul>
</div>
<ul class="storage_legend">
{list}
</ul>
"#)
}
+1 -1
View File
@@ -340,7 +340,7 @@ pub fn edit_page(
let site = context.get_site();
let head_title = playlist.title.as_deref().unwrap_or_else(|| playlist.slug());
let html = layout(context, path, &site, &body, head_title);
let html = layout(context, Some(path), &site, &body, head_title);
HttpResponse::Ok()
.content_type(ContentType::html())
+2 -2
View File
@@ -549,7 +549,7 @@ pub fn edit_page(
and all versions of the video. If the video lies at the
site root it does not remove the site manifest and the site itself,
so the site can afterwards be reinitialized again as a collection,
video or video.
playlist or video.
</p>
<form action="/delete-video/{path}" method="post">
@@ -560,7 +560,7 @@ pub fn edit_page(
let site = context.get_site();
let head_title = video.title.as_deref().unwrap_or(video.slug());
let html = layout(context, path, &site, &body, head_title);
let html = layout(context, Some(path), &site, &body, head_title);
HttpResponse::Ok()
.content_type(ContentType::html())
+54 -35
View File
@@ -20,7 +20,7 @@ fn collection_tree(
breadcrumbs: &mut Vec<String>,
collection: &Collection,
context: &Context,
path: &str
path: Option<&str>
) -> String {
let collection_icon = icons::collection(&context.editor_translations.collection);
let playlist_icon = icons::playlist(&context.editor_translations.playlist);
@@ -39,13 +39,15 @@ fn collection_tree(
.map(|collection| {
let collection_path = &collection.path;
let active = path == collection_path;
let active = path.is_some_and(|path| path == collection_path);
let href = format!("/collection/{collection_path}");
let node = tree_node(active, context, &collection.errors, &href, &collection_icon, collection.slug(), collection.title.as_deref());
if active || path
.strip_prefix(&collection.path)
.is_some_and(|rest| rest.starts_with('/')) {
if active || path.is_some_and(|path|
path
.strip_prefix(&collection.path)
.is_some_and(|rest| rest.starts_with('/'))
) {
let label = collection.title.as_deref().unwrap_or_else(|| collection.slug());
let (icon, space) = if active { (collection_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="{href}">{icon}{space}{label}</a>"#));
@@ -77,13 +79,15 @@ fn collection_tree(
.map(|playlist| {
let playlist_path = &playlist.path;
let active = path == playlist_path;
let active = path.is_some_and(|path| path == playlist_path);
let href = format!("/playlist/{playlist_path}");
let node = tree_node(active, context, &playlist.errors, &href, &playlist_icon, playlist.slug(), playlist.title.as_deref());
if active || path
.strip_prefix(&playlist.path)
.is_some_and(|rest| rest.starts_with('/')) {
if active || path.is_some_and(|path|
path
.strip_prefix(&playlist.path)
.is_some_and(|rest| rest.starts_with('/'))
) {
let label = playlist.title.as_deref().unwrap_or_else(|| playlist.slug());
let (icon, space) = if active { (playlist_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="{href}">{icon}{space}{label}</a>"#));
@@ -97,7 +101,7 @@ fn collection_tree(
.map(|video| {
let video_path = &video.path;
let active = path == video_path;
let active = path.is_some_and(|path| path == video_path);
let href = format!("/video/{video_path}");
let node = tree_node(active, context, &video.errors, &href, &video_icon, video.slug(), video.title.as_deref());
@@ -146,7 +150,7 @@ fn collection_tree(
.map(|video| {
let video_path = &video.path;
let active = path == video_path;
let active = path.is_some_and(|path| path == video_path);
let href = format!("/video/{video_path}");
let node = tree_node(active, context, &video.errors, &href, &video_icon, video.slug(), video.title.as_deref());
@@ -258,9 +262,11 @@ pub fn form_textarea(
"#)
}
/// When path is Some() that signifies we are viewing some node in the site tree.
/// If it's None we are on some auxillary page such as the dashboard or 404 page.
pub fn layout(
context: &Context,
path: &str,
path: Option<&str>,
site: &Site,
body: &str,
title: &str
@@ -339,9 +345,7 @@ pub fn layout(
{tree}
</nav>
<main>
<div class="breadcrumbs">
{breadcrumbs}
</div>
{breadcrumbs}
{body}
</main>
</div>
@@ -370,7 +374,7 @@ pub fn not_found(context: &Context, message: &str) -> HttpResponse {
"#);
let site = &context.get_site();
let html = layout(context, "", site, &body, "Not Found");
let html = layout(context, None, site, &body, "Not Found");
HttpResponse::Ok()
.content_type(ContentType::html())
@@ -379,13 +383,13 @@ pub fn not_found(context: &Context, message: &str) -> HttpResponse {
pub fn site_tree(
context: &Context,
path: &str,
path: Option<&str>,
site: &Site,
site_dir: &Path
) -> (String, String) {
let mut breadcrumbs = Vec::new();
let root_active = path == "";
let root_active = path.is_some_and(|path| path == "");
let root_dir = site_dir.file_name().unwrap().to_string_lossy();
let site_dir = &site_dir.to_string_lossy();
@@ -393,9 +397,12 @@ pub fn site_tree(
SiteContent::Collection(collection) => {
let t_collection = &context.editor_translations.collection;
let collection_icon = icons::collection(t_collection);
let breadcrumb_title = collection.title.as_deref().unwrap_or(t_collection);
let (icon, space) = if root_active { (collection_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="/collection/">{icon}{space}{breadcrumb_title}</a>"#));
if path.is_some() {
let breadcrumb_title = collection.title.as_deref().unwrap_or(t_collection);
let (icon, space) = if root_active { (collection_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="/collection/">{icon}{space}{breadcrumb_title}</a>"#));
}
let collection_content = collection_tree(&mut breadcrumbs, collection, context, path);
@@ -413,16 +420,21 @@ pub fn site_tree(
// TODO: Dedicated icon for empty site?
let collection_icon = icons::collection(t_empty_site);
breadcrumbs.push(format!(r#"<a href="/">{root_dir}</a>"#));
if path.is_some() {
breadcrumbs.push(format!(r#"<a href="/">{root_dir}</a>"#));
}
tree_node(root_active, context, &Vec::new(), "/", &collection_icon, site_dir, Some(t_empty_site))
}
SiteContent::Playlist(playlist) => {
let t_playlist = &context.editor_translations.playlist;
let playlist_icon = icons::playlist(t_playlist);
let breadcrumb_title = playlist.title.as_deref().unwrap_or(t_playlist);
let (icon, space) = if root_active { (playlist_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="/playlist/">{icon}{space}{breadcrumb_title}</a>"#));
if path.is_some() {
let breadcrumb_title = playlist.title.as_deref().unwrap_or(t_playlist);
let (icon, space) = if root_active { (playlist_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="/playlist/">{icon}{space}{breadcrumb_title}</a>"#));
}
let videos = if playlist.videos.is_empty() {
formatdoc!(r#"
@@ -447,7 +459,7 @@ pub fn site_tree(
.map(|video| {
let video_path = &video.path;
let active = path == video_path;
let active = path.is_some_and(|path| path == video_path);
let href = format!("/video/{video_path}");
let slug = video.slug();
@@ -480,21 +492,28 @@ pub fn site_tree(
let t_video = &context.editor_translations.video;
let video_icon = icons::video(t_video);
let breadcrumb_title = video.title.as_deref().unwrap_or(t_video);
let (icon, space) = if root_active { (video_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="/video/">{icon}{space}{breadcrumb_title}</a>"#));
if path.is_some() {
let breadcrumb_title = video.title.as_deref().unwrap_or(t_video);
let (icon, space) = if root_active { (video_icon.as_str(), " ") } else { ("", "") };
breadcrumbs.push(format!(r#"<a href="/video/">{icon}{space}{breadcrumb_title}</a>"#));
}
tree_node(root_active, context, &video.errors, "/video/", &video_icon, site_dir, video.title.as_deref())
}
};
let breadcrumbs = breadcrumbs.join(" › ");
let breadcrumbs = if breadcrumbs.is_empty() {
String::new()
} else {
let breadcrumbs_joined = breadcrumbs.join(" › ");
formatdoc!(r#"
<div class="breadcrumbs">
{breadcrumbs_joined}
</div>
"#)
};
let sidebar = formatdoc!(r#"
{site_content}
"#);
(breadcrumbs, sidebar)
(breadcrumbs, site_content)
}
fn tree_node(