feat: add /images image listing page

image-uploads
Jef Roosens 2025-01-24 20:15:28 +01:00
parent 39a15bb094
commit fc02399e78
No known key found for this signature in database
GPG Key ID: 21FD3D77D56BAF49
3 changed files with 38 additions and 5 deletions

View File

@ -12,7 +12,7 @@ use serde::Deserialize;
use std::{error::Error, fmt, path::Path};
pub use models::event::{Event, NewEvent, EVENT_TYPES};
pub use models::image::{Image, NewImage};
pub use models::image::{Image, ImageFilter, NewImage};
pub use models::plant::{NewPlant, Plant};
pub use models::session::Session;
pub use models::user::{NewUser, User};

View File

@ -1,14 +1,16 @@
use axum::{
extract::{DefaultBodyLimit, Multipart, Path, Request, State},
extract::{DefaultBodyLimit, Multipart, Path, Query, Request, State},
handler::Handler,
http::HeaderMap,
response::{Html, IntoResponse},
routing::{get, post},
routing::get,
Router,
};
use chrono::NaiveDate;
use futures::TryStreamExt;
use image::{codecs::jpeg::JpegEncoder, ImageReader};
use mime::Mime;
use tera::Context;
use tokio_util::io::StreamReader;
use tower::ServiceExt;
use tower_http::services::ServeFile;
@ -17,7 +19,7 @@ use std::{io::BufWriter, path::PathBuf};
use super::error::AppError;
use crate::{
db::{Image, NewImage},
db::{self, Image, NewImage, Pagination},
IMG_DIR,
};
@ -27,7 +29,7 @@ pub fn app() -> axum::Router<crate::Context> {
Router::new()
.route(
"/",
post(post_image.layer(DefaultBodyLimit::max(1024 * 1024 * 20))),
get(get_images).post(post_image.layer(DefaultBodyLimit::max(1024 * 1024 * 20))),
)
.route("/{id}/original", get(get_image_original))
.route("/{id}/thumb", get(get_image_thumb))
@ -58,6 +60,27 @@ async fn get_image(
Ok(ServeFile::new_with_mime(path, &mime).oneshot(req).await)
}
async fn get_images(
State(ctx): State<crate::Context>,
Query(page): Query<Pagination>,
Query(filter): Query<db::ImageFilter>,
headers: HeaderMap,
) -> super::Result<Html<String>> {
let images = tokio::task::spawn_blocking(move || db::Image::page(&ctx.pool, page, filter))
.await
.unwrap()?;
let mut context = Context::new();
context.insert("images", &images);
Ok(Html(super::render_view(
&ctx.tera,
"views/images.html",
&context,
&headers,
)?))
}
async fn get_image_original(
State(ctx): State<crate::Context>,
Path(id): Path<i32>,

View File

@ -0,0 +1,10 @@
<h1>Images</h1>
{% for image in images %}
<article>
<p>Date taken: {{ image.date_taken }}</p>
<p>Note: {{ image.note }}</p>
<a href="/images/{{ image.id }}/original" target="_blank">
<img src="/images/{{ image.id }}/thumb">
</a>
</article>
{% endfor %}