diff --git a/assets/themes/default/_global.scss b/assets/themes/default/_global.scss index fe92d062..23f6acec 100644 --- a/assets/themes/default/_global.scss +++ b/assets/themes/default/_global.scss @@ -507,6 +507,7 @@ figure { margin: auto $horizontal-margin 2em; overflow: auto; display: flex; + justify-content: center; a { display: inline-block; diff --git a/plume-models/src/timeline/mod.rs b/plume-models/src/timeline/mod.rs index d6b2a59d..8f80310c 100644 --- a/plume-models/src/timeline/mod.rs +++ b/plume-models/src/timeline/mod.rs @@ -6,6 +6,7 @@ use crate::{ Connection, Error, Result, }; use diesel::{self, BoolExpressionMethods, ExpressionMethods, QueryDsl, RunQueryDsl}; +use std::cmp::Ordering; use std::ops::Deref; pub(crate) mod query; @@ -85,6 +86,16 @@ impl Timeline { .or(timeline_definition::user_id.is_null()), ) .load::(conn) + .map(|mut timelines| { + timelines.sort_by(|t1, t2| { + if t1.user_id.is_some() && t2.user_id.is_none() { + Ordering::Less + } else { + Ordering::Equal + } + }); + timelines + }) .map_err(Error::from) } else { timeline_definition::table diff --git a/src/routes/instance.rs b/src/routes/instance.rs index cedaa900..526bde31 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -28,25 +28,26 @@ use plume_models::{ #[get("/")] pub fn index(conn: DbConn, rockets: PlumeRocket) -> Result { - let inst = Instance::get_local()?; - let timelines = Timeline::list_all_for_user(&conn, rockets.user.clone().map(|u| u.id))? - .into_iter() - .filter_map(|t| { - if let Ok(latest) = t.get_latest(&conn, 12) { - Some((t, latest)) - } else { - None - } - }) - .collect(); - - Ok(render!(instance::index( - &(&conn, &rockets).to_context(), - inst, - User::count_local(&conn)?, - Post::count_local(&conn)?, - timelines - ))) + let all_tl = Timeline::list_all_for_user(&conn, rockets.user.clone().map(|u| u.id))?; + if all_tl.is_empty() { + Err(Error::NotFound.into()) + } else { + let inst = Instance::get_local()?; + let page = Page::default(); + let tl = &all_tl[0]; + let posts = tl.get_page(&conn, page.limits())?; + let total_posts = tl.count_posts(&conn)?; + Ok(render!(instance::index( + &(&conn, &rockets).to_context(), + inst, + User::count_local(&conn)?, + Post::count_local(&conn)?, + tl.id, + posts, + all_tl, + Page::total(total_posts as i32) + ))) + } } #[get("/admin")] diff --git a/src/routes/mod.rs b/src/routes/mod.rs old mode 100755 new mode 100644 index b239abec..5ea53c96 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -59,6 +59,12 @@ impl From> for RespondOrRedirect { #[derive(Shrinkwrap, Copy, Clone, UriDisplayQuery)] pub struct Page(i32); +impl From for Page { + fn from(page: i32) -> Self { + Self(page) + } +} + impl<'v> FromFormValue<'v> for Page { type Error = &'v RawStr; fn from_form_value(form_value: &'v RawStr) -> Result { diff --git a/templates/instance/index.rs.html b/templates/instance/index.rs.html index 0361318e..4e25401a 100644 --- a/templates/instance/index.rs.html +++ b/templates/instance/index.rs.html @@ -4,37 +4,37 @@ @use crate::templates::{base, partials::*}; @use crate::template_utils::*; @use crate::routes::*; +@use rocket::uri; -@(ctx: BaseContext, instance: Instance, n_users: i64, n_articles: i64, all_tl: Vec<(Timeline, Vec)>) +@(ctx: BaseContext, instance: Instance, n_users: i64, n_articles: i64, tl_id: i32, articles: Vec, all_tl: Vec, n_pages: i32) @:base(ctx, instance.name.clone(), {}, {}, { -

@i18n!(ctx.1, "Welcome to {}"; instance.name.as_str())

+
+

@i18n!(ctx.1, "Welcome to {}"; instance.name.as_str())

+
- @tabs(&vec![(format!("{}", uri!(instance::index)), i18n!(ctx.1, "Latest articles"), true)] - .into_iter().chain(all_tl.clone() + @tabs(&all_tl .into_iter() - .map(|(tl, _)| { - let url = format!("{}", uri!(timelines::details: id = tl.id, page = _)); - (url, i18n_timeline_name(ctx.1, &tl.name), false) + .map(|t| { + let url = format!("{}", uri!(timelines::details: id = t.id, page = _)); + (url, i18n_timeline_name(ctx.1, &t.name), t.id == tl_id) }) - ).collect::>() + .collect::>() ) - @for (tl, articles) in all_tl { - @if !articles.is_empty() { -
-

- @i18n_timeline_name(ctx.1, &tl.name) - — - @i18n!(ctx.1, "View all") -

-
- @for article in articles { - @:post_card(ctx, article) - } -
-
- } + @if !articles.is_empty() { +
+ @for article in articles { + @:post_card(ctx, article) + } +
+ } else { +

@i18n!(ctx.1, "Nothing to see here yet.")

+ } + @if n_pages > 1 { + } @:instance_description(ctx, instance, n_users, n_articles) diff --git a/templates/timelines/details.rs.html b/templates/timelines/details.rs.html index 916b4f76..d745a4ba 100644 --- a/templates/timelines/details.rs.html +++ b/templates/timelines/details.rs.html @@ -8,21 +8,20 @@ @(ctx: BaseContext, tl: Timeline, articles: Vec, all_tl: Vec, page: i32, n_pages: i32) @:base(ctx, tl.name.clone(), {}, {}, { -
-

@i18n_timeline_name(ctx.1, &tl.name)

-
+
+

@i18n_timeline_name(ctx.1, &tl.name)

+
- @tabs(&vec![(format!("{}", uri!(instance::index)), i18n!(ctx.1, "Latest articles"), false)] - .into_iter().chain(all_tl + @tabs(&all_tl .into_iter() .map(|t| { - let url = format!("{}", uri!(timelines::details: id = t.id, page = _)); + let url = format!("{}", uri!(timelines::details: id = t.id, page = _)); (url, i18n_timeline_name(ctx.1, &t.name), t.id == tl.id) }) - ).collect::>() + .collect::>() ) - @if !articles.is_empty() { + @if !articles.is_empty() {
@for article in articles { @:post_card(ctx, article)