forked from slonk/bingus-blog
implement sorting
This commit is contained in:
parent
02216efb7d
commit
00b721caab
9 changed files with 105 additions and 30 deletions
|
@ -43,11 +43,12 @@ title = "bingus-blog" # title of the blog
|
||||||
description = "blazingly fast markdown blog software written in rust memory safe"
|
description = "blazingly fast markdown blog software written in rust memory safe"
|
||||||
markdown_access = true # allow users to see the raw markdown of a post
|
markdown_access = true # allow users to see the raw markdown of a post
|
||||||
# endpoint: /posts/<name>.md
|
# endpoint: /posts/<name>.md
|
||||||
|
js_enable = true # enable javascript (required for below 2 options)
|
||||||
date_format = "RFC3339" # format string used to format dates in the backend
|
date_format = "RFC3339" # format string used to format dates in the backend
|
||||||
# it's highly recommended to leave this as default,
|
# it's highly recommended to leave this as default,
|
||||||
# so the date can be formatted by the browser.
|
# so the date can be formatted by the browser.
|
||||||
# format: https://docs.rs/chrono/latest/chrono/format/strftime/index.html#specifiers
|
# format: https://docs.rs/chrono/latest/chrono/format/strftime/index.html#specifiers
|
||||||
js_enable = true # enable javascript (required for above)
|
default_sort = "date" # default sorting method ("date" or "name")
|
||||||
default_color = "#f5c2e7" # default embed color, optional
|
default_color = "#f5c2e7" # default embed color, optional
|
||||||
|
|
||||||
[rss]
|
[rss]
|
||||||
|
|
|
@ -14,7 +14,7 @@ use tower_http::services::ServeDir;
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
use tracing::{info, info_span, Span};
|
use tracing::{info, info_span, Span};
|
||||||
|
|
||||||
use crate::config::{Config, DateFormat};
|
use crate::config::{Config, DateFormat, Sort};
|
||||||
use crate::error::{AppError, AppResult};
|
use crate::error::{AppError, AppResult};
|
||||||
use crate::filters;
|
use crate::filters;
|
||||||
use crate::post::{MarkdownPosts, PostManager, PostMetadata, RenderStats, ReturnedPost};
|
use crate::post::{MarkdownPosts, PostManager, PostMetadata, RenderStats, ReturnedPost};
|
||||||
|
@ -35,6 +35,7 @@ struct IndexTemplate<'a> {
|
||||||
df: &'a DateFormat,
|
df: &'a DateFormat,
|
||||||
js: bool,
|
js: bool,
|
||||||
color: Option<&'a str>,
|
color: Option<&'a str>,
|
||||||
|
sort: Sort,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
|
@ -72,6 +73,7 @@ async fn index<'a>(
|
||||||
df: &config.date_format,
|
df: &config.date_format,
|
||||||
js: config.js_enable,
|
js: config.js_enable,
|
||||||
color: config.default_color.as_deref(),
|
color: config.default_color.as_deref(),
|
||||||
|
sort: config.default_sort,
|
||||||
}
|
}
|
||||||
.into_response())
|
.into_response())
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,14 +67,24 @@ pub enum DateFormat {
|
||||||
Strftime(String),
|
Strftime(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Default, Copy, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum Sort {
|
||||||
|
#[default]
|
||||||
|
Date,
|
||||||
|
Name,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub markdown_access: bool,
|
pub markdown_access: bool,
|
||||||
pub date_format: DateFormat,
|
|
||||||
pub js_enable: bool,
|
pub js_enable: bool,
|
||||||
|
pub date_format: DateFormat,
|
||||||
|
pub default_sort: Sort,
|
||||||
pub default_color: Option<String>,
|
pub default_color: Option<String>,
|
||||||
pub rss: RssConfig,
|
pub rss: RssConfig,
|
||||||
pub dirs: DirsConfig,
|
pub dirs: DirsConfig,
|
||||||
|
@ -89,8 +99,9 @@ impl Default for Config {
|
||||||
title: "bingus-blog".into(),
|
title: "bingus-blog".into(),
|
||||||
description: "blazingly fast markdown blog software written in rust memory safe".into(),
|
description: "blazingly fast markdown blog software written in rust memory safe".into(),
|
||||||
markdown_access: true,
|
markdown_access: true,
|
||||||
date_format: Default::default(),
|
|
||||||
js_enable: true,
|
js_enable: true,
|
||||||
|
date_format: Default::default(),
|
||||||
|
default_sort: Default::default(),
|
||||||
default_color: Some("#f5c2e7".into()),
|
default_color: Some("#f5c2e7".into()),
|
||||||
// i have a love-hate relationship with serde
|
// i have a love-hate relationship with serde
|
||||||
// it was engimatic at first, but then i started actually using it
|
// it was engimatic at first, but then i started actually using it
|
||||||
|
|
|
@ -50,3 +50,7 @@ pub fn collect_tags(posts: &Vec<PostMetadata>) -> Result<Vec<(String, u64)>, ask
|
||||||
|
|
||||||
Ok(tags)
|
Ok(tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn join_tags_for_meta(tags: &Vec<String>) -> Result<String, askama::Error> {
|
||||||
|
Ok(tags.join(", "))
|
||||||
|
}
|
||||||
|
|
4
static/date.js
Normal file
4
static/date.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
for (let el of document.querySelectorAll(".date-rfc3339")) {
|
||||||
|
let date = new Date(Date.parse(el.textContent));
|
||||||
|
el.textContent = date.toLocaleString();
|
||||||
|
}
|
|
@ -1,4 +1,40 @@
|
||||||
for (let el of document.querySelectorAll(".date-rfc3339")) {
|
let form = document.getElementById("sort");
|
||||||
let date = new Date(Date.parse(el.textContent));
|
let posts = document.getElementById("posts");
|
||||||
el.textContent = date.toLocaleString();
|
|
||||||
|
let postsName = document.createElement("div");
|
||||||
|
|
||||||
|
function initialSort(source, target) {
|
||||||
|
let posts = [];
|
||||||
|
for (let post of source.children) {
|
||||||
|
let title = post.firstElementChild.innerText;
|
||||||
|
posts.push([title, post.cloneNode(true)]);
|
||||||
|
}
|
||||||
|
posts.sort(([a, _1], [b, _2]) => a.toLocaleLowerCase() > b.toLocaleLowerCase());
|
||||||
|
for (let [_, post] of posts) {
|
||||||
|
target.appendChild(post);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sort(by) {
|
||||||
|
console.log("sorting by", by);
|
||||||
|
switch (by) {
|
||||||
|
case "date":
|
||||||
|
posts.style.display = "block";
|
||||||
|
postsName.style.display = "none";
|
||||||
|
break;
|
||||||
|
case "name":
|
||||||
|
postsName.style.display = "block";
|
||||||
|
posts.style.display = "none";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSort() {
|
||||||
|
if (!form) return;
|
||||||
|
for (let el of form.sort) el.addEventListener("change", () => sort(form.sort.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
initialSort(posts, postsName);
|
||||||
|
posts.parentNode.appendChild(postsName);
|
||||||
|
handleSort();
|
||||||
|
sort(form.sort.value);
|
||||||
|
|
|
@ -112,6 +112,11 @@ div.post {
|
||||||
grid-row: 3;
|
grid-row: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sort {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* BEGIN cool effect everyone liked */
|
/* BEGIN cool effect everyone liked */
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- prettier-br -->
|
<!-- prettier-br -->
|
||||||
{% if js %}
|
{% if js %}
|
||||||
|
<script src="/static/date.js" defer></script>
|
||||||
<script src="/static/main.js" defer></script>
|
<script src="/static/main.js" defer></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</head>
|
</head>
|
||||||
|
@ -25,11 +26,20 @@
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
<p>{{ description }}</p>
|
<p>{{ description }}</p>
|
||||||
<h2>posts</h2>
|
<h2>posts</h2>
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<div>
|
<div>
|
||||||
{% if posts.is_empty() %}
|
{% if posts.is_empty() %}<!-- prettier-br -->
|
||||||
there are no posts right now. check back later!
|
there are no posts right now. check back later!<!-- prettier-br -->
|
||||||
|
{% else %}<!-- prettier-br -->
|
||||||
|
{% if js %}<!-- prettier-br -->
|
||||||
|
sort by:
|
||||||
|
<form id="sort">
|
||||||
|
<input type="radio" name="sort" id="sort-date" value="date" {% if sort == Sort::Date %} checked {% endif %} />
|
||||||
|
<label for="sort-date">date</label>
|
||||||
|
<input type="radio" name="sort" id="sort-name" value="name" {% if sort == Sort::Name %} checked {% endif %} />
|
||||||
|
<label for="sort-name">name</label>
|
||||||
|
</form>
|
||||||
{% endif %}<!-- prettier-br -->
|
{% endif %}<!-- prettier-br -->
|
||||||
|
<div id="posts">
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<div class="post">
|
<div class="post">
|
||||||
<a href="/posts/{{ post.name }}"><b>{{ post.title }}</b></a>
|
<a href="/posts/{{ post.name }}"><b>{{ post.title }}</b></a>
|
||||||
|
@ -40,6 +50,8 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}<!-- prettier-br -->
|
||||||
|
</div>
|
||||||
{% let tags = posts|collect_tags %}<!-- prettier-br -->
|
{% let tags = posts|collect_tags %}<!-- prettier-br -->
|
||||||
{% if !tags.is_empty() %}
|
{% if !tags.is_empty() %}
|
||||||
<h2>tags</h2>
|
<h2>tags</h2>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="author" content="{{ meta.author }}" />
|
<meta name="author" content="{{ meta.author }}" />
|
||||||
<meta name="keywords" content="{{ meta.tags|join(", ") }}" />
|
<meta name="keywords" content="{{ meta.tags|join_tags_for_meta }}" />
|
||||||
<meta name="description" content="{{ meta.title }}" />
|
<meta name="description" content="{{ meta.title }}" />
|
||||||
<!-- you know what I really love? platforms like discord
|
<!-- you know what I really love? platforms like discord
|
||||||
favoring twitter embeds over the open standard. to color
|
favoring twitter embeds over the open standard. to color
|
||||||
|
|
Loading…
Reference in a new issue