This commit is contained in:
Sebastian Hugentobler 2024-05-06 14:17:25 +02:00
parent ead3672570
commit 6d949bb21e
Signed by: shu
GPG Key ID: BB32CF3CA052C2F0
10 changed files with 74 additions and 18 deletions

View File

@ -90,6 +90,11 @@ impl Calibre {
let conn = self.pool.get()?;
Author::has_more_authors(&conn, author_sort)
}
pub fn scalar_author(&self, id: u64) -> Result<Author, DataStoreError> {
let conn = self.pool.get()?;
Author::scalar_author(&conn, id)
}
}
#[cfg(test)]

View File

@ -47,6 +47,12 @@ impl Author {
Ok(stmt.query_row(params, Self::from_row)?)
}
pub fn scalar_author(conn: &Connection, id: u64) -> Result<Self, DataStoreError> {
let mut stmt = conn.prepare("SELECT id, name, sort FROM authors WHERE id = (:id)")?;
let params = named_params! { ":id": id };
Ok(stmt.query_row(params, Self::from_row)?)
}
pub fn has_previous_authors(
conn: &Connection,
sort_name: &str,

View File

@ -0,0 +1,39 @@
use std::sync::Arc;
use calibre_db::data::pagination::SortOrder;
use poem::{
error::InternalServerError,
handler,
web::{Data, Html, Path},
};
use tera::Context;
use crate::{
app_state::AppState, data::book::Book, handlers::error::SqliteError, templates::TEMPLATES,
};
#[handler]
pub async fn handler(
id: Path<u64>,
state: Data<&Arc<AppState>>,
) -> Result<Html<String>, poem::Error> {
let author = state.calibre.scalar_author(*id).map_err(SqliteError)?;
let books = state
.calibre
.author_books(*id, u32::MAX.into(), None, SortOrder::ASC)
.map_err(SqliteError)?;
let books = books
.iter()
.filter_map(|x| Book::full_book(x, &state))
.collect::<Vec<Book>>();
let mut context = Context::new();
context.insert("title", &author.name);
context.insert("nav", &author.name);
context.insert("books", &books);
TEMPLATES
.render("books", &context)
.map_err(InternalServerError)
.map(Html)
}

View File

@ -1,6 +1,6 @@
use std::sync::Arc;
use calibre_db::data::pagination::SortOrder;
use calibre_db::{calibre::Calibre, data::pagination::SortOrder};
use poem::{
handler,
web::{Data, Html, Path},
@ -10,25 +10,27 @@ use crate::{app_state::AppState, handlers::paginated};
#[handler]
pub async fn handler_init(state: Data<&Arc<AppState>>) -> Result<Html<String>, poem::Error> {
paginated::render(
"authors",
|| state.calibre.authors(25, None, &SortOrder::ASC),
|author| author.sort.clone(),
|cursor| state.calibre.has_previous_authors(cursor),
|cursor| state.calibre.has_more_authors(cursor),
)
authors(&state.calibre, None, &SortOrder::ASC)
}
#[handler]
pub async fn handler(
Path((cursor, sort_order)): Path<(String, SortOrder)>,
state: Data<&Arc<AppState>>,
) -> Result<Html<String>, poem::Error> {
authors(&state.calibre, Some(&cursor), &sort_order)
}
fn authors(
calibre: &Calibre,
cursor: Option<&str>,
sort_order: &SortOrder,
) -> Result<Html<String>, poem::Error> {
paginated::render(
"authors",
|| state.calibre.authors(25, Some(&cursor), &sort_order),
|| calibre.authors(25, cursor, sort_order),
|author| author.sort.clone(),
|cursor| state.calibre.has_previous_authors(cursor),
|cursor| state.calibre.has_more_authors(cursor),
|cursor| calibre.has_previous_authors(cursor),
|cursor| calibre.has_more_authors(cursor),
)
}

View File

@ -17,13 +17,13 @@ impl ResponseError for SqliteError {
fn status(&self) -> StatusCode {
match &self.0 {
DataStoreError::NoResults(_) => StatusCode::NOT_FOUND,
_ => StatusCode::BAD_GATEWAY,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn as_response(&self) -> Response {
let id = Uuid::new_v4();
let internal_msg = self.to_string();
let internal_msg = format!("{:?}", self);
let external_msg = match &self.0 {
DataStoreError::NoResults(_) => "item not found",
_ => "internal server error",

View File

@ -24,7 +24,7 @@ pub async fn handler(state: Data<&Arc<AppState>>) -> Result<Html<String>, poem::
context.insert("nav", "recent");
context.insert("books", &recent_books);
TEMPLATES
.render("recents", &context)
.render("books", &context)
.map_err(InternalServerError)
.map(Html)
}

View File

@ -18,6 +18,7 @@ mod data {
pub mod book;
}
mod handlers {
pub mod author;
pub mod authors;
pub mod books;
pub mod cover;
@ -50,6 +51,7 @@ async fn main() -> Result<(), std::io::Error> {
.at("/", get(handlers::recents::handler))
.at("/books", get(handlers::books::handler))
.at("/authors", get(handlers::authors::handler_init))
.at("/authors/:id", get(handlers::author::handler))
.at(
"/authors/:cursor/:sort_order",
get(handlers::authors::handler),

View File

@ -7,7 +7,7 @@ pub static TEMPLATES: Lazy<Tera> = Lazy::new(|| {
("base", include_str!("../templates/base.html")),
("book_card", include_str!("../templates/book_card.html")),
("authors", include_str!("../templates/authors.html")),
("recents", include_str!("../templates/recents.html")),
("books", include_str!("../templates/books.html")),
])
.expect("failed to parse tera templates");

View File

@ -1,19 +1,21 @@
{% extends "base" %}
{% block title %}
{% if has_previous %}
<a href="/authors/{{ backward_cursor }}/DESC">← back</a>
<a class="secondary" href="/authors/{{ backward_cursor }}/DESC">← back</a>
{% endif %}
{% if has_previous and has_more %}|{% endif%}
{% if has_more %}
<a href="/authors/{{ forward_cursor }}/ASC">more →</a>
<a class="secondary" href="/authors/{{ forward_cursor }}/ASC">more →</a>
{% endif %}
{% endblock title %}
{% block content %}
<div class="grid-container">
{% for author in authors %}
<a class="contrast" href="/authors/{{ author.id }}">
<article>{{ author.name }}</article>
</a>
{% endfor %}
</div>
{% endblock content %}