Add layout and feeds page, add hotwire
This commit is contained in:
parent
74f353b894
commit
a67ffbbbed
20
src/handlers/feeds.rs
Normal file
20
src/handlers/feeds.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use axum::extract::State;
|
||||||
|
use axum::response::Response;
|
||||||
|
use maud::html;
|
||||||
|
use sqlx::PgPool;
|
||||||
|
|
||||||
|
use crate::error::Result;
|
||||||
|
use crate::models::feed::get_feeds;
|
||||||
|
use crate::partials::layout::Layout;
|
||||||
|
|
||||||
|
pub async fn get(State(pool): State<PgPool>, layout: Layout) -> Result<Response> {
|
||||||
|
let feeds = get_feeds(&pool).await?;
|
||||||
|
Ok(layout.render(html! {
|
||||||
|
ul {
|
||||||
|
@for feed in feeds {
|
||||||
|
@let title = feed.title.unwrap_or_else(|| "Untitled Feed".to_string());
|
||||||
|
li { (title) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
@ -1,20 +1,20 @@
|
|||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use maud::{html, Markup};
|
use axum::response::Response;
|
||||||
|
use maud::html;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::models::entry::get_entries;
|
use crate::models::entry::get_entries;
|
||||||
use crate::partials::header::header;
|
use crate::partials::layout::Layout;
|
||||||
|
|
||||||
pub async fn get(State(pool): State<PgPool>) -> Result<Markup> {
|
pub async fn get(State(pool): State<PgPool>, layout: Layout) -> Result<Response> {
|
||||||
let entries = get_entries(&pool).await?;
|
let entries = get_entries(&pool).await?;
|
||||||
Ok(html! {
|
Ok(layout.render(html! {
|
||||||
(header())
|
|
||||||
ul {
|
ul {
|
||||||
@for entry in entries {
|
@for entry in entries {
|
||||||
@let title = entry.title.unwrap_or_else(|| "Untitled".to_string());
|
@let title = entry.title.unwrap_or_else(|| "Untitled".to_string());
|
||||||
li { (title) }
|
li { (title) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod home;
|
pub mod home;
|
||||||
|
pub mod feeds;
|
||||||
|
@ -26,7 +26,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
sqlx::migrate!().run(&pool).await?;
|
sqlx::migrate!().run(&pool).await?;
|
||||||
|
|
||||||
let app = Router::new()
|
let mut app = Router::new()
|
||||||
.route("/api/v1/feeds", get(handlers::api::feeds::get))
|
.route("/api/v1/feeds", get(handlers::api::feeds::get))
|
||||||
.route("/api/v1/feed", post(handlers::api::feed::post))
|
.route("/api/v1/feed", post(handlers::api::feed::post))
|
||||||
.route("/api/v1/feed/:id", get(handlers::api::feed::get))
|
.route("/api/v1/feed/:id", get(handlers::api::feed::get))
|
||||||
@ -34,14 +34,18 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.route("/api/v1/entry", post(handlers::api::entry::post))
|
.route("/api/v1/entry", post(handlers::api::entry::post))
|
||||||
.route("/api/v1/entry/:id", get(handlers::api::entry::get))
|
.route("/api/v1/entry/:id", get(handlers::api::entry::get))
|
||||||
.route("/", get(handlers::home::get))
|
.route("/", get(handlers::home::get))
|
||||||
|
.route("/feeds", get(handlers::feeds::get))
|
||||||
.with_state(pool)
|
.with_state(pool)
|
||||||
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));
|
.layer(ServiceBuilder::new().layer(TraceLayer::new_for_http()));
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
let livereload = LiveReloadLayer::new();
|
let livereload = LiveReloadLayer::new();
|
||||||
let reloader = livereload.reloader();
|
let reloader = livereload.reloader();
|
||||||
let mut watcher = notify::recommended_watcher(move |_| reloader.reload())?;
|
let mut watcher = notify::recommended_watcher(move |_| reloader.reload())?;
|
||||||
watcher.watch(Path::new("target/debug/crawlnicle"), notify::RecursiveMode::Recursive)?;
|
watcher.watch(Path::new("target/debug/crawlnicle"), notify::RecursiveMode::Recursive)?;
|
||||||
let app = app.layer(livereload);
|
app = app.layer(livereload);
|
||||||
|
}
|
||||||
|
|
||||||
let addr = (env::var("HOST")? + ":" + &env::var("PORT")?).parse()?;
|
let addr = (env::var("HOST")? + ":" + &env::var("PORT")?).parse()?;
|
||||||
debug!("listening on {}", addr);
|
debug!("listening on {}", addr);
|
||||||
|
47
src/partials/layout.rs
Normal file
47
src/partials/layout.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use axum::{
|
||||||
|
async_trait,
|
||||||
|
extract::FromRequestParts,
|
||||||
|
http::request::Parts,
|
||||||
|
response::{Html, IntoResponse, Response},
|
||||||
|
};
|
||||||
|
use maud::{DOCTYPE, html, Markup};
|
||||||
|
|
||||||
|
use crate::partials::header::header;
|
||||||
|
|
||||||
|
pub struct Layout;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<S> FromRequestParts<S> for Layout
|
||||||
|
where
|
||||||
|
S: Send + Sync,
|
||||||
|
{
|
||||||
|
type Rejection = std::convert::Infallible;
|
||||||
|
|
||||||
|
async fn from_request_parts(_parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
||||||
|
// extract whatever your layout needs
|
||||||
|
Ok(Self {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Layout {
|
||||||
|
pub fn render(self, template: Markup) -> Response {
|
||||||
|
let with_layout = html! {
|
||||||
|
(DOCTYPE)
|
||||||
|
html lang="en" {
|
||||||
|
head {
|
||||||
|
meta charset="utf-8";
|
||||||
|
title { "crawlnicle" }
|
||||||
|
script type="module" {
|
||||||
|
r#"import * as Turbo from 'https://cdn.skypack.dev/@hotwired/turbo';"#
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
(header())
|
||||||
|
(template)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.into_string();
|
||||||
|
|
||||||
|
Html(with_layout).into_response()
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,2 @@
|
|||||||
pub mod header;
|
pub mod header;
|
||||||
|
pub mod layout;
|
||||||
|
Loading…
Reference in New Issue
Block a user