aboutsummaryrefslogtreecommitdiff
path: root/src/handlers
diff options
context:
space:
mode:
authorXe Iaso <me@christine.website>2022-11-25 19:01:10 -0500
committerGitHub <noreply@github.com>2022-11-25 19:01:10 -0500
commitcc933b31fd23bb06e95bf41f848a1c99353d44ae (patch)
treeaf8288dbd4db2ad886d6b326bffb1c9d5b568de3 /src/handlers
parent551e0384c923ff3ee98cfddf7e3eb42c6dbb2941 (diff)
downloadxesite-cc933b31fd23bb06e95bf41f848a1c99353d44ae.tar.xz
xesite-cc933b31fd23bb06e95bf41f848a1c99353d44ae.zip
Start version 3 (#573)
* Start version 3 * Change version to 3.0.0 in Cargo.toml * Add metadata for series * Change types for signal boosts * Add start of LaTeX resume generation at Nix time * Add start of proper author tagging for posts in JSONFeed and ldjson * Convert templates to use Maud * Add start of dynamic resume generation from dhall * Make patrons page embed thumbnails TODO: * [ ] Remove the rest of the old templates * [ ] Bring in Xeact for the share on mastodon button * [ ] Site update post Signed-off-by: Xe <me@christine.website> * fix nix builds Signed-off-by: Xe Iaso <me@christine.website> * fix dhall build Signed-off-by: Xe Iaso <me@christine.website> * fix non-flakes build Signed-off-by: Xe Iaso <me@christine.website> * make new mastodon share button Signed-off-by: Xe Iaso <me@christine.website> * remove the rest of the ructe templates that I can remove Signed-off-by: Xe Iaso <me@christine.website> * refactor blogposts to its own file Signed-off-by: Xe Iaso <me@christine.website> * move resume to be generated by nix Signed-off-by: Xe Iaso <me@christine.website> * write article Signed-off-by: Xe Iaso <me@christine.website> * blog/site-update-v3: hero image Signed-off-by: Xe Iaso <me@christine.website> * add site update series tag to site updates Signed-off-by: Xe Iaso <me@christine.website> Signed-off-by: Xe <me@christine.website> Signed-off-by: Xe Iaso <me@christine.website>
Diffstat (limited to 'src/handlers')
-rw-r--r--src/handlers/blog.rs66
-rw-r--r--src/handlers/gallery.rs28
-rw-r--r--src/handlers/mod.rs77
-rw-r--r--src/handlers/talks.rs28
4 files changed, 89 insertions, 110 deletions
diff --git a/src/handlers/blog.rs b/src/handlers/blog.rs
index 012a7ad..feeab44 100644
--- a/src/handlers/blog.rs
+++ b/src/handlers/blog.rs
@@ -1,14 +1,15 @@
use super::Result;
-use crate::{app::State, post::Post, templates};
+use crate::{app::State, post::Post, tmpl};
use axum::{
extract::{Extension, Path},
- response::Html,
+ http::StatusCode,
};
use http::HeaderMap;
use lazy_static::lazy_static;
+use maud::Markup;
use prometheus::{opts, register_int_counter_vec, IntCounterVec};
use std::sync::Arc;
-use tracing::{error, instrument};
+use tracing::instrument;
lazy_static! {
static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!(
@@ -19,40 +20,27 @@ lazy_static! {
}
#[instrument(skip(state))]
-pub async fn index(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Markup> {
let state = state.clone();
- let mut result: Vec<u8> = vec![];
- templates::blogindex_html(&mut result, state.blog.clone())?;
- Ok(Html(result))
+ let result = tmpl::post_index(&state.blog, "Blogposts", true);
+ Ok(result)
}
#[instrument(skip(state))]
-pub async fn series(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn series(Extension(state): Extension<Arc<State>>) -> Result<Markup> {
let state = state.clone();
- let mut series: Vec<String> = vec![];
- let mut result: Vec<u8> = vec![];
- for post in &state.blog {
- if post.front_matter.series.is_some() {
- series.push(post.front_matter.series.as_ref().unwrap().clone());
- }
- }
-
- series.sort();
- series.dedup();
-
- templates::series_html(&mut result, series)?;
- Ok(Html(result))
+ Ok(tmpl::blog_series(&state.cfg.clone().series_descriptions))
}
#[instrument(skip(state))]
pub async fn series_view(
Path(series): Path<String>,
Extension(state): Extension<Arc<State>>,
-) -> Result {
+) -> (StatusCode, Markup) {
let state = state.clone();
+ let cfg = state.cfg.clone();
let mut posts: Vec<Post> = vec![];
- let mut result: Vec<u8> = vec![];
for post in &state.blog {
if post.front_matter.series.is_none() {
@@ -64,13 +52,25 @@ pub async fn series_view(
posts.push(post.clone());
}
+ posts.reverse();
+
+ let desc = cfg.series_desc_map.get(&series);
+
if posts.len() == 0 {
- error!("series not found");
- return Err(super::Error::SeriesNotFound(series));
+ (
+ StatusCode::NOT_FOUND,
+ tmpl::error(format!("series not found: {series}")),
+ )
+ } else {
+ if let Some(desc) = desc {
+ (StatusCode::OK, tmpl::series_view(&series, desc, &posts))
+ } else {
+ (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ tmpl::error(format!("series metadata in dhall not found: {series}")),
+ )
+ }
}
-
- templates::series_posts_html(&mut result, series, &posts).unwrap();
- Ok(Html(result))
}
#[instrument(skip(state, headers))]
@@ -78,7 +78,7 @@ pub async fn post_view(
Path(name): Path<String>,
Extension(state): Extension<Arc<State>>,
headers: HeaderMap,
-) -> Result {
+) -> Result<(StatusCode, Markup)> {
let mut want: Option<Post> = None;
let want_link = format!("blog/{}", name);
@@ -96,15 +96,13 @@ pub async fn post_view(
};
match want {
- None => Err(super::Error::PostNotFound(name)),
+ None => Ok((StatusCode::NOT_FOUND, tmpl::not_found(want_link))),
Some(post) => {
HIT_COUNTER
.with_label_values(&[name.clone().as_str()])
.inc();
- let body = templates::Html(post.body_html.clone());
- let mut result: Vec<u8> = vec![];
- templates::blogpost_html(&mut result, post, body, referer)?;
- Ok(Html(result))
+ let body = maud::PreEscaped(&post.body_html);
+ Ok((StatusCode::OK, tmpl::blog::blog(&post, body, referer)))
}
}
}
diff --git a/src/handlers/gallery.rs b/src/handlers/gallery.rs
index ae6c411..25c8dfa 100644
--- a/src/handlers/gallery.rs
+++ b/src/handlers/gallery.rs
@@ -1,10 +1,8 @@
-use super::{Error::*, Result};
-use crate::{app::State, post::Post, templates};
-use axum::{
- extract::{Extension, Path},
- response::Html,
-};
+use crate::{app::State, post::Post, tmpl};
+use axum::extract::{Extension, Path};
+use http::StatusCode;
use lazy_static::lazy_static;
+use maud::Markup;
use prometheus::{opts, register_int_counter_vec, IntCounterVec};
use std::sync::Arc;
use tracing::instrument;
@@ -18,36 +16,32 @@ lazy_static! {
}
#[instrument(skip(state))]
-pub async fn index(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn index(Extension(state): Extension<Arc<State>>) -> Markup {
let state = state.clone();
- let mut result: Vec<u8> = vec![];
- templates::galleryindex_html(&mut result, state.gallery.clone())?;
- Ok(Html(result))
+ tmpl::gallery_index(&state.gallery)
}
#[instrument(skip(state))]
pub async fn post_view(
Path(name): Path<String>,
Extension(state): Extension<Arc<State>>,
-) -> Result {
+) -> (StatusCode, Markup) {
let mut want: Option<Post> = None;
+ let link = format!("gallery/{}", name);
for post in &state.gallery {
- if post.link == format!("gallery/{}", name) {
+ if post.link == link {
want = Some(post.clone());
}
}
match want {
- None => Err(PostNotFound(name)),
+ None => (StatusCode::NOT_FOUND, tmpl::not_found(link)),
Some(post) => {
HIT_COUNTER
.with_label_values(&[name.clone().as_str()])
.inc();
- let body = templates::Html(post.body_html.clone());
- let mut result: Vec<u8> = vec![];
- templates::gallerypost_html(&mut result, post, body)?;
- Ok(Html(result))
+ (StatusCode::OK, tmpl::blog::gallery(&post))
}
}
}
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs
index 37fcac1..a20d654 100644
--- a/src/handlers/mod.rs
+++ b/src/handlers/mod.rs
@@ -1,4 +1,4 @@
-use crate::{app::State, templates};
+use crate::{app::State, tmpl};
use axum::{
body,
extract::Extension,
@@ -7,6 +7,7 @@ use axum::{
};
use chrono::{Datelike, Timelike, Utc, Weekday};
use lazy_static::lazy_static;
+use maud::Markup;
use prometheus::{opts, register_int_counter_vec, IntCounterVec};
use std::sync::Arc;
use tracing::instrument;
@@ -67,82 +68,74 @@ lazy_static! {
};
}
-#[instrument]
-pub async fn index() -> Result {
+#[instrument(skip(state))]
+pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Markup> {
HIT_COUNTER.with_label_values(&["index"]).inc();
- let mut result: Vec<u8> = vec![];
- templates::index_html(&mut result)?;
- Ok(Html(result))
+ let state = state.clone();
+ let cfg = state.cfg.clone();
+
+ Ok(tmpl::index(&cfg.default_author, &cfg.notable_projects))
}
-#[instrument]
-pub async fn contact() -> Result {
+#[instrument(skip(state))]
+pub async fn contact(Extension(state): Extension<Arc<State>>) -> Markup {
HIT_COUNTER.with_label_values(&["contact"]).inc();
- let mut result: Vec<u8> = vec![];
- templates::contact_html(&mut result)?;
- Ok(Html(result))
+ let state = state.clone();
+ let cfg = state.cfg.clone();
+
+ crate::tmpl::contact(&cfg.contact_links)
}
#[instrument]
-pub async fn feeds() -> Result {
+pub async fn feeds() -> Markup {
HIT_COUNTER.with_label_values(&["feeds"]).inc();
- let mut result: Vec<u8> = vec![];
- templates::feeds_html(&mut result)?;
- Ok(Html(result))
+ crate::tmpl::feeds()
}
#[axum_macros::debug_handler]
#[instrument(skip(state))]
-pub async fn salary_transparency(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn salary_transparency(Extension(state): Extension<Arc<State>>) -> Result<Markup> {
HIT_COUNTER
.with_label_values(&["salary_transparency"])
.inc();
let state = state.clone();
- let mut result: Vec<u8> = vec![];
- templates::salary_transparency(&mut result, state.cfg.clone())?;
- Ok(Html(result))
+ let cfg = state.cfg.clone();
+
+ Ok(tmpl::salary_transparency(&cfg.job_history))
}
#[axum_macros::debug_handler]
-#[instrument(skip(state))]
-pub async fn resume(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn resume() -> Markup {
HIT_COUNTER.with_label_values(&["resume"]).inc();
- let state = state.clone();
- let mut result: Vec<u8> = vec![];
- templates::resume_html(&mut result, templates::Html(state.resume.clone()))?;
- Ok(Html(result))
+
+ tmpl::resume()
}
#[instrument(skip(state))]
-pub async fn patrons(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn patrons(Extension(state): Extension<Arc<State>>) -> (StatusCode, Markup) {
HIT_COUNTER.with_label_values(&["patrons"]).inc();
let state = state.clone();
- let mut result: Vec<u8> = vec![];
match &state.patrons {
- None => Err(Error::NoPatrons),
- Some(patrons) => {
- templates::patrons_html(&mut result, patrons.clone())?;
- Ok(Html(result))
- }
+ None => (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ tmpl::error("Patreon API config is broken, no patrons in ram"),
+ ),
+ Some(patrons) => (StatusCode::IM_A_TEAPOT, tmpl::patrons(&patrons)),
}
}
#[axum_macros::debug_handler]
#[instrument(skip(state))]
-pub async fn signalboost(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn signalboost(Extension(state): Extension<Arc<State>>) -> Markup {
HIT_COUNTER.with_label_values(&["signalboost"]).inc();
let state = state.clone();
- let mut result: Vec<u8> = vec![];
- templates::signalboost_html(&mut result, state.signalboost.clone())?;
- Ok(Html(result))
+ tmpl::signalboost(&state.signalboost)
}
#[instrument]
-pub async fn not_found() -> Result {
+pub async fn not_found(uri: axum::http::Uri) -> (StatusCode, Markup) {
HIT_COUNTER.with_label_values(&["not_found"]).inc();
- let mut result: Vec<u8> = vec![];
- templates::notfound_html(&mut result, "some path".into())?;
- Ok(Html(result))
+ (StatusCode::NOT_FOUND, tmpl::not_found(uri.path()))
}
#[derive(Debug, thiserror::Error)]
@@ -170,8 +163,8 @@ pub type Result<T = Html<Vec<u8>>> = std::result::Result<T, Error>;
impl IntoResponse for Error {
fn into_response(self) -> Response {
- let mut result: Vec<u8> = vec![];
- templates::error_html(&mut result, format!("{}", self)).unwrap();
+ let result = tmpl::error(format!("{}", self));
+ let result = result.0;
let body = body::boxed(body::Full::from(result));
diff --git a/src/handlers/talks.rs b/src/handlers/talks.rs
index 59d8676..262e481 100644
--- a/src/handlers/talks.rs
+++ b/src/handlers/talks.rs
@@ -1,11 +1,9 @@
-use super::{Error::*, Result};
-use crate::{app::State, post::Post, templates};
-use axum::{
- extract::{Extension, Path},
- response::Html,
-};
-use http::header::HeaderMap;
+use super::Result;
+use crate::{app::State, post::Post, tmpl};
+use axum::extract::{Extension, Path};
+use http::{header::HeaderMap, StatusCode};
use lazy_static::lazy_static;
+use maud::Markup;
use prometheus::{opts, register_int_counter_vec, IntCounterVec};
use std::sync::Arc;
use tracing::instrument;
@@ -19,11 +17,9 @@ lazy_static! {
}
#[instrument(skip(state))]
-pub async fn index(Extension(state): Extension<Arc<State>>) -> Result {
+pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Markup> {
let state = state.clone();
- let mut result: Vec<u8> = vec![];
- templates::talkindex_html(&mut result, state.talks.clone())?;
- Ok(Html(result))
+ Ok(tmpl::post_index(&state.talks, "Talks", false))
}
#[instrument(skip(state, headers))]
@@ -31,7 +27,7 @@ pub async fn post_view(
Path(name): Path<String>,
Extension(state): Extension<Arc<State>>,
headers: HeaderMap,
-) -> Result {
+) -> Result<(StatusCode, Markup)> {
let mut want: Option<Post> = None;
let want_link = format!("talks/{}", name);
@@ -49,15 +45,13 @@ pub async fn post_view(
};
match want {
- None => Err(PostNotFound(name).into()),
+ None => Ok((StatusCode::NOT_FOUND, tmpl::not_found(want_link))),
Some(post) => {
HIT_COUNTER
.with_label_values(&[name.clone().as_str()])
.inc();
- let body = templates::Html(post.body_html.clone());
- let mut result: Vec<u8> = vec![];
- templates::talkpost_html(&mut result, post, body, referer)?;
- Ok(Html(result))
+ let body = maud::PreEscaped(&post.body_html);
+ Ok((StatusCode::OK, tmpl::blog::talk(&post, body, referer)))
}
}
}