Add page navigation

This commit is contained in:
Mikko Ahlroth 2024-04-05 14:42:19 +03:00
parent 8907487e32
commit a8e801bf8c
6 changed files with 146 additions and 4 deletions

View file

@ -39,6 +39,21 @@ body > footer {
grid-area: footer;
}
.page-nav ul {
list-style-type: none;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: baseline;
gap: 0.2rem;
}
.page-nav ul li a {
display: inline-block;
padding: 0.8rem;
}
#tags {
list-style-type: none;
font-size: 2.75rem;
@ -76,3 +91,26 @@ body > footer {
margin: 0;
padding: 0;
}
.post header nav ul {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: baseline;
gap: 0.5rem;
margin: 0;
}
.post header nav ul li {
margin: 0;
}
.post footer {
text-align: left;
margin: 0;
padding-left: 0;
padding-right: 0;
}

View file

@ -99,6 +99,7 @@ fn render_index_pages(
posts_with_contents,
renderers,
"",
config.paths.index,
element.none(),
)
}
@ -119,6 +120,7 @@ fn render_tag_pages(
posts_with_contents,
renderers,
tag,
config.paths.tag(tag),
element.none(),
)
})
@ -150,6 +152,7 @@ fn render_year_pages(
posts_with_contents,
renderers,
"Archives for " <> int.to_string(year),
config.paths.year(year),
element.none(),
)
})
@ -178,6 +181,7 @@ fn render_month_pages(
<> date.month_to_string(month)
<> " "
<> int.to_string(year),
config.paths.month(year, month),
element.none(),
),
)
@ -191,6 +195,7 @@ fn pageify_posts(
posts_with_contents: Dict(PostID, RenderedPost),
renderers: Renderers,
title_prefix: String,
root_path: String,
extra_header: Element(Nil),
) {
let posts = list.sized_chunk(posts, config.rendering.posts_per_page)
@ -200,6 +205,7 @@ fn pageify_posts(
let info =
ListInfo(
root_path: root_path,
current_page: page,
total_pages: total_pages,
posts: list.map(page_posts, fn(post_with_id) {

View file

@ -13,6 +13,7 @@ pub type SinglePostRenderer =
pub type ListInfo {
ListInfo(
root_path: String,
current_page: Int,
total_pages: Int,
posts: List(RenderedPost),

View file

@ -1,9 +1,10 @@
import gleam/list
import lustre/element
import lustre/element/html
import lustre/attribute.{class}
import lustre/element/html.{footer, nav}
import lustre/attribute.{attribute, class}
import gloss/models/database.{type Database}
import gloss/rendering/templates.{type ListInfo}
import gloss/rendering/templates/nav
import gloss/config.{type Configuration}
pub fn generate(db: Database, config: Configuration) {
@ -13,6 +14,14 @@ pub fn generate(db: Database, config: Configuration) {
fn(info: ListInfo) {
let none = element.none()
let footer = case info.total_pages > 1 {
True ->
nav([class("page-nav"), attribute("aria-label", "Pages")], [
footer([], [nav.view(info, info.root_path, config)]),
])
False -> none
}
html.section(
[class("post-list")],
list.flatten([
@ -21,7 +30,7 @@ pub fn generate(db: Database, config: Configuration) {
el -> [el]
},
list.map(info.posts, single_post_renderer),
[html.footer([], [])],
[footer],
]),
)
}

View file

@ -0,0 +1,84 @@
import gleam/list
import gleam/int
import lustre/element/html.{a, li, span, ul}
import lustre/element.{text}
import lustre/attribute.{attribute, href}
import gloss/rendering/templates.{type ListInfo}
import gloss/config.{type Configuration}
pub fn view(list_info: ListInfo, root_path: String, config: Configuration) {
let page_range = list.range(1, list_info.total_pages)
ul(
[],
list.flatten([
[
nextprev_link(
list_info.current_page > 1,
list_info.current_page - 1,
"Previous",
"«",
root_path,
config,
),
],
list.map(page_range, fn(page) {
let link_text = case page == list_info.current_page {
True -> "[" <> int.to_string(page) <> "]"
False -> int.to_string(page)
}
let link_attributes = case page == list_info.current_page {
True -> [
attribute("aria-label", int.to_string(page) <> " (current page)"),
attribute("aria-disabled", "true"),
]
False -> []
}
li([], [
a(
list.flatten([
[href(config.paths.html(config.paths.list_page(root_path, page)))],
link_attributes,
]),
[text(link_text)],
),
])
}),
[
nextprev_link(
list_info.current_page < list_info.total_pages,
list_info.current_page + 1,
"Next",
"»",
root_path,
config,
),
],
]),
)
}
fn nextprev_link(
condition: Bool,
target: Int,
label: String,
text: String,
root_path: String,
config: Configuration,
) {
case condition {
True ->
li([], [
a(
[
href(config.paths.html(config.paths.list_page(root_path, target))),
attribute("aria-label", label),
],
[span([attribute("aria-hidden", "true")], [element.text(text)])],
),
])
False -> element.none()
}
}

View file

@ -47,7 +47,11 @@ fn view(post: RenderedPost, is_full: Bool, _db: Database, config: Configuration)
nav([attribute("aria-label", "Tags")], [
ul(
[],
list.map(post.orig.tags, fn(tag) { li([], [a([], [text(tag)])]) }),
list.map(post.orig.tags, fn(tag) {
li([], [
a([href(config.paths.html(config.paths.tag(tag)))], [text(tag)]),
])
}),
),
]),
]),