diff --git a/Cargo.lock b/Cargo.lock index 4240a5c..b8add0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -512,6 +512,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + [[package]] name = "futures-task" version = "0.3.31" @@ -602,6 +608,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + [[package]] name = "httparse" version = "1.9.5" @@ -1164,6 +1176,19 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "tower" version = "0.5.2" @@ -1188,9 +1213,18 @@ checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" dependencies = [ "bitflags", "bytes", + "futures-util", "http", "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", "pin-project-lite", + "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", diff --git a/Cargo.toml b/Cargo.toml index fc07c5e..24645ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ axum = "0.7.9" tower = "0.5.2" tracing = "0.1.41" tracing-subscriber = "0.3.19" -tower-http = { version = "0.6.2", features = ["cors", "trace"] } +tower-http = { version = "0.6.2", features = ["cors", "trace", "fs"] } chrono = "0.4.39" diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } dotenvy = "0.15" diff --git a/assets/galaxy.jpg b/assets/galaxy.jpg new file mode 100644 index 0000000..31bca1e Binary files /dev/null and b/assets/galaxy.jpg differ diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..2927c10 --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main.rs b/src/main.rs index 8a8ab41..877b1bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,7 @@ use tower::{ServiceBuilder}; use tower_http::{ cors::{Any, CorsLayer}, trace::{TraceLayer, DefaultOnResponse}, + services::ServeDir, LatencyUnit }; use tracing::{ @@ -96,7 +97,9 @@ async fn main() -> Result<()> { .layer(tracelayer).layer(cors); // Launch Web Server let app = Router::new() + .nest_service("/assets", ServeDir::new("assets")) .route("/", get(index)) + .route("/feed/:id/", get(get_feed)) .layer(middlewares) .with_state(context.clone()); // Run our app with hyper @@ -104,32 +107,59 @@ async fn main() -> Result<()> { .await.context(format!("Failed to bind Web Service on {}:{}", config.http_host, config.http_port))?; info!("Listening on {}:{}", config.http_host, config.http_port); axum::serve(listener, app).await.context("Failed to serve Web Service")?; - // let connection = &mut establish_connection(); - // use self::schema::rss_feeds::dsl::*; - // let results = rss_feeds - // .limit(5) - // .select(RssFeed::as_select()) - // .load(connection) - // .expect("Error loading posts"); - // - // println!("Displaying {} posts", results.len()); - // for rss_feed in results { - // println!("{}", rss_feed.name); - // println!("-----------\n"); - // println!("{}", rss_feed.feed_url); - // } Ok(()) } +#[derive(Template)] +#[template(path="feed.html")] +struct FeedTemplate { + feed: RssFeed +} + +async fn get_feed( + State(ctx): State, + Path(feed_id): Path +) -> FeedTemplate { + let conn = ctx.pool.get().await.unwrap(); + use self::schema::rss_feeds::dsl::*; + let result = conn.interact(move |conn| { + rss_feeds + .find(feed_id) + .select(RssFeed::as_select()) + .first(conn) + .optional() + .expect("Error loading feeds") + }).await.unwrap(); + if let Some(feed) = result { + FeedTemplate{ feed } + } else { + FeedTemplate{ + feed: RssFeed{ + id: -1, + name: "ERROR".to_string(), + feed_url: "ERROR".to_string(), + last_pub_date: Some("ERROR".to_string()) + } + } + } +} #[derive(Template)] #[template(path = "index.html")] -struct HelloTemplate<'a> { - name: &'a str, +struct IndexTemplate { + feeds: Vec, } async fn index( State(ctx): State, -) -> HelloTemplate<'static> { - HelloTemplate { name: "world" } +) -> IndexTemplate { + let conn = ctx.pool.get().await.unwrap(); + use self::schema::rss_feeds::dsl::*; + let result = conn.interact(|conn| { + rss_feeds + .select(RssFeed::as_select()) + .load(conn) + .expect("Error loading feeds") + }).await.unwrap(); + IndexTemplate { feeds: result } } diff --git a/templates/base.html b/templates/base.html index 6be5dd7..9d1c6ec 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,7 +1,8 @@ - + + {% block title %}{{ title }}{% endblock %} {% block head %}{% endblock %} diff --git a/templates/feed.html b/templates/feed.html new file mode 100644 index 0000000..ba5f100 --- /dev/null +++ b/templates/feed.html @@ -0,0 +1,13 @@ + + {{feed.name}} + {{feed.feed_url}} + {{feed.last_pub_date.clone().unwrap_or("None".to_string())}} + + + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 041834e..1c1736c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,6 +2,29 @@ {% block title %}Hello!{% endblock %} -{% block content %} -

Hello, {{name}}!

+{% block head %} +{% endblock %} + +{% block content %} + +
+
+ + + + + + + + {% for feed in feeds %} + {% include "feed.html" %} + {% endfor %} +
Feed NameFeed URLLast Mail SentActions
{% endblock %}