Add page resolver

This commit is contained in:
Evie Viau-Chow-Stuart 2023-02-04 18:42:08 -08:00
parent 78cb11b54a
commit 37d6c3cd4d
Signed by: evie
GPG key ID: 928652CDFCEC8099
6 changed files with 150 additions and 14 deletions

View file

@ -1,4 +1,4 @@
*:80 {
127.0.0.1 {
route /favicon.ico {
file_server {
root ./static

View file

@ -3,7 +3,7 @@ use std::str::FromStr;
use axum::{Router, routing::get};
use log::info;
use sea_orm::{Database, DatabaseConnection};
use sea_orm::{Database, DatabaseConnection, ConnectOptions};
mod routes;
mod entities;
@ -11,7 +11,9 @@ mod block_types;
#[tokio::main]
async fn main() {
env::set_var("RUST_LOG", "info");
if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "info");
}
tracing_subscriber::fmt::init();
dotenvy::dotenv().ok();
@ -26,7 +28,10 @@ async fn main() {
info!("Connecting to the database...");
let db_conn = Database::connect(db_url)
let mut db_opt = ConnectOptions::new(db_url);
db_opt.sqlx_logging_level(log::LevelFilter::Debug);
let db_conn = Database::connect(db_opt)
.await
.expect("Failed to connect to the database! HALTING");
//Migrator::up(&db_conn, None).await.expect("Failed to run migrations! HALTING");
@ -37,6 +42,8 @@ async fn main() {
let app = Router::new()
.route("/", get(routes::root))
.route("/post/:slug", get(not_implemented))
.route("/:slug", get(routes::page_resolver::resolver))
.with_state(app_state);
info!("Attempting to bind to address...");
@ -48,13 +55,14 @@ async fn main() {
match bind {
Ok(bind) => {
info!("Binded to address successfully!");
info!("Started!");
bind.serve(app.into_make_service())
.await
.unwrap();
info!("Listening for connections...");
match bind.serve(app.into_make_service()).await {
Err(e) => panic!("Failed to start server! HALTING {}", e),
_ => (),
}
},
Err(_) => {
panic!("Failed to bind! HALTING")
Err(e) => {
panic!("Failed to bind! HALTING {}", e)
},
}
}
@ -63,3 +71,7 @@ async fn main() {
struct AppState {
db_conn: DatabaseConnection,
}
async fn not_implemented() -> &'static str {
"Not Implemented"
}

View file

@ -1,9 +1,41 @@
pub(crate) mod page_resolver;
use askama::Template;
use crate::{block_types::BlockTypes, AppState};
#[derive(Template)]
#[template(path = "page.html")]
pub(crate) struct PageTemplate {
title: String,
description: Option<String>,
show_title: bool,
content_blocks: Vec<BlockTypes>,
year: String
}
#[derive(Template)]
#[template(path = "post.html")]
pub(crate) struct PostTemplate {
title: String,
summary: Option<String>,
publish_date: String,
last_updated: Option<String>,
content_blocks: Vec<BlockTypes>,
year: String,
}
#[derive(Template)]
#[template(path = "notfound.html")]
pub(crate) struct NotFoundTemplate {
slug: String,
year: String
}
use axum::extract::State;
use log::warn;
use crate::block_types;
use crate::{block_types::BlockTypes, AppState};
use crate::entities::{prelude::*, *};
use sea_orm::*;
@ -36,7 +68,6 @@ pub(crate) async fn root(
.await
.expect("Failed to get home page blocks! HALTING");
// TODO: should move this into its own func, it'll be reused a bit
let content_blocks: Vec<BlockTypes> = blocks.into_iter().map(|f|
match f.r#type.as_str() {
"HR" => BlockTypes::HR,

View file

@ -0,0 +1,67 @@
use askama_axum::IntoResponse;
use axum::extract::{State, Path};
use axum::http::StatusCode;
use log::{warn, error};
use crate::block_types;
use crate::{block_types::BlockTypes, AppState};
use crate::entities::{prelude::*, *};
use sea_orm::*;
use super::{PageTemplate, NotFoundTemplate};
pub(crate) async fn resolver(
Path(slug): Path<String>,
state: State<AppState>
) -> impl IntoResponse {
let page_search: Result<Option<page::Model>, DbErr> = Page::find()
.filter(page::Column::Slug.eq(&slug))
.one(&state.db_conn)
.await;
let page_meta: page::Model = match page_search {
Ok(page_result) => {
match page_result {
Some(page_result) => page_result,
None => return (StatusCode::NOT_FOUND, NotFoundTemplate { slug, year: "2023".to_owned() }).into_response(),
}
},
Err(e) => {
error!("{}", e);
return (StatusCode::INTERNAL_SERVER_ERROR, ()).into_response();
},
};
let blocks: Vec<page_block::Model> = page_meta.find_related(PageBlock)
.order_by_asc(page_block::Column::Order)
.all(&state.db_conn)
.await
.expect("Failed to get home page blocks! HALTING");
let content_blocks: Vec<BlockTypes> = blocks.into_iter().map(|f|
match f.r#type.as_str() {
"HR" => BlockTypes::HR,
"PARAGRAPH" => BlockTypes::PARAGRAPH { text: f.content },
"MARKDOWN" => BlockTypes::MARKDOWN { content: f.content },
"HEADER" => {
let deserde: block_types::Header = serde_json::from_str(&f.content.as_str()).expect("Incorrect HEADER formatting");
BlockTypes::HEADER { text: deserde.text, size: deserde.size
}
}
_ => {
warn!("Unsupported block type! ({})", f.r#type.as_str());
BlockTypes::UNSUPPORTED
}
}
).collect();
(StatusCode::FOUND, PageTemplate {
title: page_meta.clone().title,
description: page_meta.clone().description,
show_title: page_meta.clone().show_title,
content_blocks,
year: "2023".to_string()
}).into_response()
}

15
templates/notfound.html Normal file
View file

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% block title %}404{% endblock %}
{% block description %}
This page wasn't found!
{% endblock %}
{% block content %}
<h1>Page not found!</h1>
<p><code>{{ slug }}</code> was not found! Would you like to go <a href="/">home</a>?</p>
{% endblock %}

View file

@ -27,8 +27,19 @@
<br />
{% for block in blocks %}
<p>block is real</p>
{% for content_block in content_blocks %}
{% match content_block %}
{% when BlockTypes::HR %}
<hr />
{% when BlockTypes::PARAGRAPH { text } %}
<p>{{ text }}</p>
{% when BlockTypes::MARKDOWN { content } %}
{{ content|markdown }}
{% when BlockTypes::HEADER { text, size } %}
<h{{size}}>{{text}}</h{{size}}>
{% when BlockTypes::UNSUPPORTED %}
<b>UNSUPPORTED block type here!</b>
{% endmatch %}
{% endfor %}
<br />