A little app to serve my photography from my personal website

create projects views

ericwood.org 83dde85c 9ee4fd09

Waiting for spindle ...
+144 -18
+2 -2
src/routes/projects/index.rs
··· 1 1 use crate::{ 2 2 AppState, Response, 3 - views::{View, blog::BlogIndex}, 3 + views::{View, projects::ProjectsIndex}, 4 4 }; 5 5 use axum::{ 6 6 extract::{Query, State}, ··· 22 22 }; 23 23 24 24 let tags = state.project_store.all_tags(); 25 - let view = BlogIndex::new(posts, tags, query.tag.clone()); 25 + let view = ProjectsIndex::new(posts, tags, query.tag.clone()); 26 26 let html = view.render(&state.reloader)?; 27 27 28 28 Ok(Html(html))
+2 -2
src/routes/projects/show.rs
··· 1 - use crate::views::{View, blog::BlogShow}; 1 + use crate::views::{View, projects::ProjectsShow}; 2 2 use crate::{AppState, Response, app_error::AppError}; 3 3 use axum::{ 4 4 extract::{Path, State}, ··· 17 17 return Ok(Html(html)); 18 18 } 19 19 20 - let view = BlogShow::new(post); 20 + let view = ProjectsShow::new(post); 21 21 let html = view.render(&state.reloader)?; 22 22 23 23 Ok(Html(html))
src/views/blog/show/syntax.css src/styles/syntax.css
+5 -4
src/views/blog/show/template.jinja
··· 1 1 {% extends "layout" %} 2 2 {% set active_page = 'blog' %} 3 - {% block title %}Blog{% endblock %} 3 + {% block title %}Blog / {{ post.title }}{% endblock %} 4 4 {% block head %} 5 5 {{ inline_style("src/views/blog/show/style.css") }} 6 + {{ inline_style("src/styles/posts.css") }} 6 7 {% if has_code %} 7 - {{ inline_style("src/views/blog/show/syntax.css") }} 8 + {{ inline_style("src/styles/syntax.css") }} 8 9 {% endif %} 9 10 {% endblock %} 10 11 {% block body %} 11 - <div class="blog__layout"> 12 + <div class="layout"> 12 13 <div class="blog__header"> 13 14 <h1 class="blog__title">{{ post.title }}</h1> 14 15 <div> 15 - <span class="blog__tags-title">Posted</span> 16 + <span class="post__tags-title">Posted</span> 16 17 <time datetime="{{ post.published_at }}">{{ post.published_at }}</time> 17 18 </div> 18 19 <div class="blog__tags">
+1 -10
src/views/mod.rs
··· 2 2 3 3 pub mod blog; 4 4 pub mod photos; 5 + pub mod projects; 5 6 6 7 pub trait View { 7 8 fn render(&self, reloader: &AutoReloader) -> anyhow::Result<String>; 8 9 } 9 - 10 - // 11 - // views 12 - // - photos 13 - // - show 14 - // - show.jinja 15 - // - show.rs 16 - // - show.js 17 - // - show.css 18 - // - index
+34
src/views/projects/index/mod.rs
··· 1 + use std::sync::Arc; 2 + 3 + use minijinja::context; 4 + use minijinja_autoreload::AutoReloader; 5 + 6 + use crate::{post::Post, templates::render, views::View}; 7 + 8 + pub struct ProjectsIndex { 9 + posts: Vec<Arc<Post>>, 10 + tags: Vec<(String, usize)>, 11 + tag: Option<String>, 12 + } 13 + 14 + impl ProjectsIndex { 15 + pub fn new(posts: Vec<Arc<Post>>, tags: Vec<(String, usize)>, tag: Option<String>) -> Self { 16 + Self { posts, tags, tag } 17 + } 18 + } 19 + 20 + impl View for ProjectsIndex { 21 + fn render(&self, reloader: &AutoReloader) -> anyhow::Result<String> { 22 + let html = render( 23 + reloader, 24 + "views/projects/index", 25 + context! { 26 + posts => self.posts, 27 + tags => self.tags, 28 + tag => self.tag, 29 + }, 30 + )?; 31 + 32 + Ok(html) 33 + } 34 + }
src/views/projects/index/style.css

This is a binary file and will not be displayed.

+20
src/views/projects/index/template.jinja
··· 1 + {% extends "layout" %} 2 + {% set active_page = 'projects' %} 3 + {% block title %}Projects{% endblock %} 4 + {% block head %} 5 + {{ inline_style("src/views/projects/index/style.css") }} 6 + {{ inline_style("src/styles/posts.css") }} 7 + {% endblock %} 8 + {% import "posts" as posts_macro %} 9 + 10 + {% block body %} 11 + <div class="layout"> 12 + {{ posts_macro.header("Projects", tag=tag) }} 13 + {{ posts_macro.table(posts, root_path="/projects", tag=tag) }} 14 + </div> 15 + <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="display: none"> 16 + <defs> 17 + <path id="close-icon" d="M20.7457 3.32851C20.3552 2.93798 19.722 2.93798 19.3315 3.32851L12.0371 10.6229L4.74275 3.32851C4.35223 2.93798 3.71906 2.93798 3.32854 3.32851C2.93801 3.71903 2.93801 4.3522 3.32854 4.74272L10.6229 12.0371L3.32856 19.3314C2.93803 19.722 2.93803 20.3551 3.32856 20.7457C3.71908 21.1362 4.35225 21.1362 4.74277 20.7457L12.0371 13.4513L19.3315 20.7457C19.722 21.1362 20.3552 21.1362 20.7457 20.7457C21.1362 20.3551 21.1362 19.722 20.7457 19.3315L13.4513 12.0371L20.7457 4.74272C21.1362 4.3522 21.1362 3.71903 20.7457 3.32851Z" fill="currentColor"/> 18 + </defs> 19 + </svg> 20 + {% endblock %}
+5
src/views/projects/mod.rs
··· 1 + mod index; 2 + mod show; 3 + 4 + pub use index::ProjectsIndex; 5 + pub use show::ProjectsShow;
+38
src/views/projects/show/mod.rs
··· 1 + use std::sync::Arc; 2 + 3 + use minijinja::context; 4 + use minijinja_autoreload::AutoReloader; 5 + 6 + use crate::{ 7 + post::{Post, render_post}, 8 + templates::render, 9 + views::View, 10 + }; 11 + 12 + pub struct ProjectsShow { 13 + post: Arc<Post>, 14 + } 15 + 16 + impl ProjectsShow { 17 + pub fn new(post: Arc<Post>) -> Self { 18 + Self { post } 19 + } 20 + } 21 + 22 + impl View for ProjectsShow { 23 + fn render(&self, reloader: &AutoReloader) -> anyhow::Result<String> { 24 + let (body, _) = render_post(&self.post.file_path)?; 25 + let has_code = body.contains("<pre class=\"highlighted\">"); 26 + let html = render( 27 + reloader, 28 + "views/projects/show", 29 + context! { 30 + post => self.post, 31 + body, 32 + has_code, 33 + }, 34 + )?; 35 + 36 + Ok(html) 37 + } 38 + }
+37
src/views/projects/show/template.jinja
··· 1 + {% extends "layout" %} 2 + {% set active_page = 'projects' %} 3 + {% block title %}Projects / {{ post.title }}{% endblock %} 4 + {% block head %} 5 + {{ inline_style("src/views/blog/show/style.css") }} 6 + {{ inline_style("src/styles/posts.css") }} 7 + {% if has_code %} 8 + {{ inline_style("src/styles/syntax.css") }} 9 + {% endif %} 10 + {% endblock %} 11 + {% block body %} 12 + <div class="layout"> 13 + <div class="blog__header"> 14 + <h1 class="blog__title">{{ post.title }}</h1> 15 + <div> 16 + <span class="post__tags-title">Posted</span> 17 + <time datetime="{{ post.published_at }}">{{ post.published_at }}</time> 18 + </div> 19 + <div class="blog__tags"> 20 + <span class="blog__tags-title">Filed Under</span> 21 + <ul class="blog__tag-list"> 22 + {% for tag in post.tags %} 23 + <li><a class="tag" href="/projects?tag={{ tag }}">{{ tag }}</a></li> 24 + {% endfor %} 25 + </ul> 26 + </div> 27 + </div> 28 + <div class="blog__container"> 29 + <div class="blog__body"> 30 + {{ body }} 31 + </div> 32 + <div class="blog__toc"> 33 + {{ toc_html }} 34 + </div> 35 + </div> 36 + </div> 37 + {% endblock %}