render: implement pagination

This commit is contained in:
Peter Cai 2020-04-10 20:57:53 +08:00
parent e599007ed4
commit 1110a2614b
No known key found for this signature in database
GPG Key ID: 71F5FB4E4F3FD54F
4 changed files with 53 additions and 8 deletions

View File

@ -120,7 +120,7 @@ async fn default_route(_req: Request, url: Url) -> MyResult<Response> {
// Home page (this cannot be registered as a standalone route due to our Router) // Home page (this cannot be registered as a standalone route due to our Router)
if path == "/" { if path == "/" {
return Response::new_with_opt_str_and_init( return Response::new_with_opt_str_and_init(
Some(&render::render_homepage().await?), Some(&render::render_homepage(url).await?),
ResponseInit::new() ResponseInit::new()
.status(200) .status(200)
.headers(headers!{ .headers(headers!{

View File

@ -55,7 +55,9 @@ struct HomePagePost {
#[derive(Serialize)] #[derive(Serialize)]
struct HomePageContext { struct HomePageContext {
blog: &'static BlogRootContext, blog: &'static BlogRootContext,
posts: Vec<HomePagePost> posts: Vec<HomePagePost>,
prev: Option<String>,
next: Option<String>
} }
lazy_static! { lazy_static! {
@ -98,14 +100,51 @@ fn build_handlebars() -> Handlebars<'static> {
return hbs; return hbs;
} }
pub async fn render_homepage() -> MyResult<String> { pub async fn render_homepage(url: Url) -> MyResult<String> {
let params = UrlSearchParams::new_with_str(&url.search())
.map_err(|_| Error::BadRequest("Failed to parse query string".into()))?;
let hbs = build_handlebars(); let hbs = build_handlebars();
let mut context = HomePageContext { let mut context = HomePageContext {
blog: &ROOT_CONTEXT, blog: &ROOT_CONTEXT,
posts: vec![] posts: vec![],
prev: None,
next: None
}; };
let posts_list = blog::PostsList::load().await; let posts_list = blog::PostsList::load().await;
for uuid in posts_list.0.iter() {
// Pagination
let mut posts_len = posts_list.0.len();
let mut offset: isize = 0;
if let Some(offset_str) = params.get("offset") {
offset = offset_str.parse().internal_err()?;
if offset > posts_len as isize || offset < 0 {
return Err(Error::BadRequest("invalid offset".into()));
}
posts_len = posts_len - offset as usize;
}
if offset > 0 {
let new_offset =
std::cmp::max(offset - crate::CONFIG.posts_per_page as isize, 0) as usize;
if new_offset != 0 {
context.prev = Some(format!("/?offset={}", new_offset));
} else {
context.prev = Some("/".into());
}
}
if posts_len == 0 {
return Err(Error::BadRequest("offset too large".into()));
}
if posts_len > crate::CONFIG.posts_per_page {
context.next = Some(
format!("/?offset={}",
offset + crate::CONFIG.posts_per_page as isize));
}
// List posts
for uuid in posts_list.0.iter().skip(offset as usize).take(crate::CONFIG.posts_per_page) {
let post = blog::Post::find_by_uuid(uuid).await?; let post = blog::Post::find_by_uuid(uuid).await?;
let post_cache = blog::PostContentCache::find_or_render(&post).await; let post_cache = blog::PostContentCache::find_or_render(&post).await;
context.posts.push(HomePagePost { context.posts.push(HomePagePost {

View File

@ -153,7 +153,9 @@ pub struct Config {
// Description of the blog // Description of the blog
pub description: String, pub description: String,
// Plugin identifier used for Standard Notes // Plugin identifier used for Standard Notes
pub plugin_identifier: String pub plugin_identifier: String,
// How many posts to show in one page
pub posts_per_page: usize
} }
#[derive(BuildDateTime)] #[derive(BuildDateTime)]

View File

@ -19,8 +19,12 @@
</article> </article>
{{ /each }} {{ /each }}
<div class="pagination"> <div class="pagination">
<a href="#"><span class="page-older"></span></a> {{ #if next }}
<a href="#"><span class="page-newer"></span></a> <a href="{{ next }}"><span class="page-older"></span></a>
{{ /if }}
{{ #if prev }}
<a href="{{ prev }}"><span class="page-newer"></span></a>
{{ /if }}
</div> </div>
</div> </div>
</div> </div>