diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2022-06-08 00:03:08 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2022-06-08 00:43:44 -0400 |
| commit | 63ff3d96d329db74f1703a6dc775cefcaa617823 (patch) | |
| tree | 1218878195a8cd0977612b4c69480e4e0a5f2264 /src/view.rs | |
| parent | 9fa89e735859d008673663b740c217d0731e71e1 (diff) | |
Move to Askama templates.
The author of maud seems to be slow on updating to newer actix releases, and the syntax, while clever, is ultimately less tool-friendly than "HTML with some weird characters" is.
I do still like the idea, but I also want to use Actix 4.
Diffstat (limited to 'src/view.rs')
| -rw-r--r-- | src/view.rs | 155 |
1 files changed, 34 insertions, 121 deletions
diff --git a/src/view.rs b/src/view.rs index ad26607..9393d25 100644 --- a/src/view.rs +++ b/src/view.rs @@ -8,7 +8,7 @@ //! //! ``` //! # use things_to_check::view; -//! # #[actix_rt::main] +//! # #[actix_web::main] //! # async fn main() -> std::result::Result<(), things_to_check::view::Error> { //! use actix_web::{App, HttpServer}; //! @@ -61,7 +61,7 @@ //! parameter to the `/` endpoint is a literal index into this list. use actix_web::{error, get, post, web, HttpRequest, HttpResponse, Responder}; -use maud::{html, Markup, PreEscaped, DOCTYPE}; +use askama::Template; use pulldown_cmark::{html, Options, Parser}; use rand::seq::SliceRandom; use rand::thread_rng; @@ -95,11 +95,22 @@ impl From<UrlError> for error::Error { } trait Urls { - fn index_url(&self, query: ItemQuery) -> Result<url::Url, UrlError>; + fn index(&self, query: &ItemQuery) -> Result<url::Url, UrlError>; + + // Askama always passes parameters from templates to functions as borrows, + // regardless of type; receiving a reference to a usize is silly, but as a + // result, necessary. + fn suggestion(&self, idx: &usize) -> Result<url::Url, UrlError> { + self.index(&ItemQuery::from(*idx)) + } + + fn new_suggestion(&self) -> Result<url::Url, UrlError> { + self.index(&ItemQuery::default()) + } } impl Urls for HttpRequest { - fn index_url(&self, query: ItemQuery) -> Result<url::Url, UrlError> { + fn index(&self, query: &ItemQuery) -> Result<url::Url, UrlError> { let mut url = self.url_for("index", iter::empty::<&str>())?; let query = serde_urlencoded::to_string(query)?; @@ -114,116 +125,18 @@ struct ItemQuery { item: Option<usize>, } -impl From<&usize> for ItemQuery { - fn from(idx: &usize) -> Self { - ItemQuery { item: Some(*idx) } - } -} - -type MarkupResult = Result<Markup, error::Error>; - -fn page(head: impl FnOnce() -> MarkupResult, body: impl FnOnce() -> MarkupResult) -> MarkupResult { - Ok(html! { - (DOCTYPE) - html { - head { - (head()?) - } - body { - (body()?) - } - } - }) -} - -fn stylesheet() -> Markup { - html! { - style { - (PreEscaped(" - body { - background: #dddde7; - font-color: #888; - font-family: Helvetica, sans-serif; - display: flex; - flex-direction: column; - justify-content: center; - height: 100vh; - margin: 0; - } - - section { - width: 600px; - margin: auto; - } - - p { - font-size: 24px; - } - - a { - text-decoration: none; - } - ")) - } +impl From<usize> for ItemQuery { + fn from(idx: usize) -> Self { + ItemQuery { item: Some(idx) } } } -fn og_card(title: &str, description: &str) -> Markup { - html! { - meta property="og:type" content="website"; - meta property="og:title" content=(title); - meta property="og:description" content=(description); - } -} - -fn suggestion_link( - req: &impl Urls, - query: ItemQuery, - body: impl FnOnce() -> MarkupResult, -) -> MarkupResult { - Ok(html! { - p { - a href=( req.index_url(query)? ) { (body()?) } - } - }) -} - -fn github_badge(repo: &str) -> Markup { - html! { - a href={ "https://github.com/" (repo) } { - img - style="position: absolute; top: 0; right: 0; border: 0;" - src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" - alt="Fork me on GitHub" - data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"; - } - } -} - -fn index_view(req: impl Urls, idx: &usize, thing: &Thing) -> MarkupResult { - page( - || { - Ok(html! { - title { (thing.markdown) } - (stylesheet()) - (og_card("Troubleshooting suggestion", &thing.markdown)) - }) - }, - || { - Ok(html! { - section { - (PreEscaped(&thing.html)) - (suggestion_link(&req, ItemQuery::default(), || Ok(html! { - "That wasn't it, suggest something else." - }))?) - (suggestion_link(&req, ItemQuery::from(idx), || Ok(html! { - "Share this troubleshooting suggestion." - }))?) - } - (github_badge("ojacobson/things-to-check")) - }) - }, - ) +#[derive(Template)] +#[template(path = "index.html")] +struct Suggestion { + thing: Thing, + req: HttpRequest, + index: usize, } #[get("/")] @@ -237,12 +150,15 @@ async fn index( None => data.0.choose(&mut thread_rng()), }; - let (index, thing) = match thing { - Some(x) => x, - None => return Err(error::ErrorNotFound("Not found")), - }; + let thing = thing.ok_or_else(|| error::ErrorNotFound("Not found"))?; + let (index, thing) = thing.to_owned(); - Ok(index_view(req, index, thing)?.with_header("Cache-Control", "no-store")) + let response = Suggestion { thing, req, index }; + let response = response + .customize() + .insert_header(("Cache-Control", "no-store")); + + Ok(response) } #[derive(Serialize)] @@ -255,10 +171,7 @@ struct SlackMessage<'a> { async fn slack_troubleshoot(data: web::Data<Things>) -> error::Result<impl Responder> { let thing = data.0.choose(&mut thread_rng()); - let (_, thing) = match thing { - Some(x) => x, - None => return Err(error::ErrorNotFound("Not found")), - }; + let (_, thing) = thing.ok_or_else(|| error::ErrorNotFound("Not found"))?; let response = SlackMessage { response_type: "in_channel", @@ -320,7 +233,7 @@ pub fn make_service() -> Result<impl Fn(&mut web::ServiceConfig) + Clone, Error> let things = load_things(THINGS)?; Ok(move |cfg: &mut web::ServiceConfig| { - cfg.data(things.clone()) + cfg.app_data(web::Data::new(things.clone())) .service(index) .service(slack_troubleshoot); }) |
