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 super::error::AppError;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{self, Image, NewImage, Pagination},
|
db::{self, Image, NewImage, Pagination},
|
||||||
template::{Template, View},
|
template::{List, ListCard, Template, View},
|
||||||
IMG_DIR,
|
IMG_DIR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,17 +72,11 @@ async fn get_images(
|
||||||
.await
|
.await
|
||||||
.unwrap()?;
|
.unwrap()?;
|
||||||
|
|
||||||
let mut context = Context::new();
|
let list = List::Card
|
||||||
context.insert("images", &images);
|
.items("Images", ListCard::Image, images)
|
||||||
|
.page("/images", page)
|
||||||
let is_final_page = images.len() < page.per_page.try_into().unwrap();
|
.query(filter);
|
||||||
context.insert("is_final_page", &is_final_page);
|
Ok(Html(View::other(list).headers(&headers).render(&ctx.tera)?))
|
||||||
|
|
||||||
Ok(Html(
|
|
||||||
View::Images
|
|
||||||
.headers(&headers)
|
|
||||||
.render_ctx(&ctx.tera, &context)?,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_image_original(
|
async fn get_image_original(
|
||||||
|
|
|
@ -67,7 +67,7 @@ async fn get_plants(
|
||||||
|
|
||||||
let list = List::Ul
|
let list = List::Ul
|
||||||
.items("Plants", ListItem::Plant, plants)
|
.items("Plants", ListItem::Plant, plants)
|
||||||
.page("/plants", page, None);
|
.page("/plants", page);
|
||||||
Ok(Html(View::other(list).headers(&headers).render(&ctx.tera)?))
|
Ok(Html(View::other(list).headers(&headers).render(&ctx.tera)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct Query(pub Vec<(String, String)>);
|
pub struct Query(pub Vec<(String, String)>);
|
||||||
|
|
||||||
impl Query {
|
impl Query {
|
||||||
|
|
|
@ -11,16 +11,22 @@ use super::Template;
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum List {
|
pub enum List {
|
||||||
Ul,
|
Ul,
|
||||||
|
Card,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ListItem {
|
pub enum ListItem {
|
||||||
Plant,
|
Plant,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ListCard {
|
||||||
|
Image,
|
||||||
|
}
|
||||||
|
|
||||||
impl Template for List {
|
impl Template for List {
|
||||||
fn template(&self) -> &'static str {
|
fn template(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
List::Ul => "list/ul.html",
|
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 {
|
impl List {
|
||||||
pub fn items<T: Template, I: Serialize>(
|
pub fn items<T: Template, I: Serialize>(
|
||||||
self,
|
self,
|
||||||
|
@ -45,7 +59,8 @@ impl List {
|
||||||
heading,
|
heading,
|
||||||
item_tmpl,
|
item_tmpl,
|
||||||
items,
|
items,
|
||||||
next_page_url: None,
|
next_page: None,
|
||||||
|
query: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,21 +70,26 @@ pub struct ListWrapper<T: Template, I: Serialize> {
|
||||||
heading: &'static str,
|
heading: &'static str,
|
||||||
item_tmpl: T,
|
item_tmpl: T,
|
||||||
items: Vec<I>,
|
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> {
|
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 {
|
if self.items.len() as u32 == page.per_page {
|
||||||
page.page += 1;
|
page.page += 1;
|
||||||
|
|
||||||
let query = if let Some(query) = query {
|
self.next_page = Some((url, page));
|
||||||
query.join(page)
|
}
|
||||||
} else {
|
|
||||||
page.to_query()
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
self
|
||||||
|
@ -99,8 +119,15 @@ impl<T: Template, I: Serialize> Template for ListWrapper<T, I> {
|
||||||
ctx.insert("heading", &self.heading);
|
ctx.insert("heading", &self.heading);
|
||||||
ctx.insert("items", &items);
|
ctx.insert("items", &items);
|
||||||
|
|
||||||
if let Some(next_page_url) = &self.next_page_url {
|
if let Some((url, page)) = &self.next_page {
|
||||||
ctx.insert("next_page_url", &next_page_url);
|
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)
|
self.render_ctx(tera, &ctx)
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod list;
|
||||||
mod update;
|
mod update;
|
||||||
mod view;
|
mod view;
|
||||||
|
|
||||||
pub use list::{List, ListItem};
|
pub use list::{List, ListCard, ListItem};
|
||||||
pub use update::Update;
|
pub use update::Update;
|
||||||
pub use view::View;
|
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