feat: migrate /images page to new typed methods
							parent
							
								
									4e92c02e63
								
							
						
					
					
						commit
						b17c2e7df6
					
				|  | @ -20,7 +20,7 @@ use std::{io::BufWriter, path::PathBuf}; | |||
| use super::error::AppError; | ||||
| use crate::{ | ||||
|     db::{self, Image, NewImage, Pagination}, | ||||
|     template::{Template, View}, | ||||
|     template::{List, ListCard, Template, View}, | ||||
|     IMG_DIR, | ||||
| }; | ||||
| 
 | ||||
|  | @ -72,17 +72,11 @@ async fn get_images( | |||
|             .await | ||||
|             .unwrap()?; | ||||
| 
 | ||||
|     let mut context = Context::new(); | ||||
|     context.insert("images", &images); | ||||
| 
 | ||||
|     let is_final_page = images.len() < page.per_page.try_into().unwrap(); | ||||
|     context.insert("is_final_page", &is_final_page); | ||||
| 
 | ||||
|     Ok(Html( | ||||
|         View::Images | ||||
|             .headers(&headers) | ||||
|             .render_ctx(&ctx.tera, &context)?, | ||||
|     )) | ||||
|     let list = List::Card | ||||
|         .items("Images", ListCard::Image, images) | ||||
|         .page("/images", page) | ||||
|         .query(filter); | ||||
|     Ok(Html(View::other(list).headers(&headers).render(&ctx.tera)?)) | ||||
| } | ||||
| 
 | ||||
| async fn get_image_original( | ||||
|  |  | |||
|  | @ -67,7 +67,7 @@ async fn get_plants( | |||
| 
 | ||||
|     let list = List::Ul | ||||
|         .items("Plants", ListItem::Plant, plants) | ||||
|         .page("/plants", page, None); | ||||
|         .page("/plants", page); | ||||
|     Ok(Html(View::other(list).headers(&headers).render(&ctx.tera)?)) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| use serde::Serialize; | ||||
| 
 | ||||
| #[derive(Serialize)] | ||||
| #[derive(Serialize, Clone)] | ||||
| pub struct Query(pub Vec<(String, String)>); | ||||
| 
 | ||||
| impl Query { | ||||
|  |  | |||
|  | @ -11,16 +11,22 @@ use super::Template; | |||
| #[derive(Clone, Copy)] | ||||
| pub enum List { | ||||
|     Ul, | ||||
|     Card, | ||||
| } | ||||
| 
 | ||||
| pub enum ListItem { | ||||
|     Plant, | ||||
| } | ||||
| 
 | ||||
| pub enum ListCard { | ||||
|     Image, | ||||
| } | ||||
| 
 | ||||
| impl Template for List { | ||||
|     fn template(&self) -> &'static str { | ||||
|         match self { | ||||
|             List::Ul => "list/ul.html", | ||||
|             List::Card => "list/card.html", | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -33,6 +39,14 @@ impl Template for ListItem { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Template for ListCard { | ||||
|     fn template(&self) -> &'static str { | ||||
|         match self { | ||||
|             Self::Image => "card/image.html", | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl List { | ||||
|     pub fn items<T: Template, I: Serialize>( | ||||
|         self, | ||||
|  | @ -45,7 +59,8 @@ impl List { | |||
|             heading, | ||||
|             item_tmpl, | ||||
|             items, | ||||
|             next_page_url: None, | ||||
|             next_page: None, | ||||
|             query: None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -55,21 +70,26 @@ pub struct ListWrapper<T: Template, I: Serialize> { | |||
|     heading: &'static str, | ||||
|     item_tmpl: T, | ||||
|     items: Vec<I>, | ||||
|     next_page_url: Option<String>, | ||||
|     next_page: Option<(&'static str, Pagination)>, | ||||
|     query: Option<Query>, | ||||
| } | ||||
| 
 | ||||
| impl<T: Template, I: Serialize> ListWrapper<T, I> { | ||||
|     pub fn page(mut self, url: &'static str, mut page: Pagination, query: Option<Query>) -> Self { | ||||
|     pub fn page(mut self, url: &'static str, mut page: Pagination) -> Self { | ||||
|         if self.items.len() as u32 == page.per_page { | ||||
|             page.page += 1; | ||||
| 
 | ||||
|             let query = if let Some(query) = query { | ||||
|                 query.join(page) | ||||
|             } else { | ||||
|                 page.to_query() | ||||
|             }; | ||||
|             self.next_page = Some((url, page)); | ||||
|         } | ||||
| 
 | ||||
|             self.next_page_url = Some(format!("{url}?{}", query.encode())); | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn query(mut self, query: impl ToQuery) -> Self { | ||||
|         if let Some(old_query) = self.query { | ||||
|             self.query = Some(old_query.join(query)); | ||||
|         } else { | ||||
|             self.query = Some(query.to_query()); | ||||
|         } | ||||
| 
 | ||||
|         self | ||||
|  | @ -99,8 +119,15 @@ impl<T: Template, I: Serialize> Template for ListWrapper<T, I> { | |||
|         ctx.insert("heading", &self.heading); | ||||
|         ctx.insert("items", &items); | ||||
| 
 | ||||
|         if let Some(next_page_url) = &self.next_page_url { | ||||
|             ctx.insert("next_page_url", &next_page_url); | ||||
|         if let Some((url, page)) = &self.next_page { | ||||
|             let query = if let Some(query) = &self.query { | ||||
|                 query.clone().join(page.clone()) | ||||
|             } else { | ||||
|                 page.to_query() | ||||
|             }; | ||||
| 
 | ||||
|             let full_url = format!("{url}?{}", query.encode()); | ||||
|             ctx.insert("next_page_url", &full_url); | ||||
|         } | ||||
| 
 | ||||
|         self.render_ctx(tera, &ctx) | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ mod list; | |||
| mod update; | ||||
| mod view; | ||||
| 
 | ||||
| pub use list::{List, ListItem}; | ||||
| pub use list::{List, ListCard, ListItem}; | ||||
| pub use update::Update; | ||||
| pub use view::View; | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,9 @@ | |||
| {% import "components/plant.html" as comp_plant %} | ||||
| <article> | ||||
|     <p>Date taken: {{ item.0.date_taken }}</p> | ||||
|     <p>Note: {{ item.0.note }}</p> | ||||
|     <p>Plant: {{ comp_plant::name(plant=item.1) }}</p> | ||||
|     <a href="/images/{{ item.0.id }}/original" target="_blank"> | ||||
|         <img src="/images/{{ item.0.id }}/thumb"> | ||||
|     </a> | ||||
| </article> | ||||
|  | @ -0,0 +1,18 @@ | |||
| <h1>{{ heading }}</h1> | ||||
| 
 | ||||
| <div id="items"> | ||||
| {% for item in items %} | ||||
|     {{ item | safe }} | ||||
| {% endfor %} | ||||
| 
 | ||||
| {% if next_page_url %} | ||||
| <div  | ||||
|     aria-busy="true" | ||||
|     hx-get="{{ next_page_url }}" | ||||
|     hx-select="#items > *" | ||||
|     hx-trigger="revealed" | ||||
|     hx-target="this" | ||||
|     hx-swap="outerHTML"> | ||||
| </div> | ||||
| {% endif %} | ||||
| </div> | ||||
		Loading…
	
		Reference in New Issue