Start roughing in series management

- Set up asset struct for rust-embed. Create SQL assets.
- Write convenience for loading SQL assets.
- Rough out view series route.
- Rough out and wire up add series route.
This commit is contained in:
Thomas Gideon 2024-09-07 13:18:23 -04:00
parent ddb06d2993
commit 3d3b08caf1
7 changed files with 68 additions and 4 deletions

1
sql/insert_series.sql Normal file
View file

@ -0,0 +1 @@
insert into series (name) values ($1);

1
sql/select_series.sql Normal file
View file

@ -0,0 +1 @@
select * from series;

View file

@ -1,9 +1,13 @@
use super::series::SeriesList;
use super::series::{add::AddSeries, SeriesList};
use leptos::*;
use leptos_router::*;
#[component]
pub fn HomePage() -> impl IntoView {
let add_series = create_server_action::<AddSeries>();
provide_context(add_series);
view! {
<h1 class="mt-3 mb-5">"What We're Watching"</h1>
<div class="row">

View file

@ -1,15 +1,48 @@
use leptos::*;
use leptos_router::*;
#[component]
pub fn AddSeries() -> impl IntoView {
let add_series = expect_context::<Action<AddSeries, Result<(), ServerFnError>>>();
view! {
<div class="card p-3">
<div class="card-heading">
<h2>Add Series</h2>
</div>
<div class="card-body">
To Do
<ActionForm action=add_series>
<div class="input-group mb-3">
<input type="text"
name="name"
class="form-control"
/>
</div>
<div>
<input type="submit"
class="btn btn-primary"
value="Add Series"
/>
</div>
</ActionForm>
</div>
</div>
}
}
#[server(AddSeries)]
pub async fn add_series(name: String) -> Result<(), ServerFnError> {
use crate::db::load_statement;
use sqlx::{Pool, Postgres};
let pool = expect_context::<Pool<Postgres>>();
let s = load_statement("insert_series.sql");
sqlx::query(&s)
.persistent(true)
.bind(name)
.execute(&pool)
.await?;
leptos_axum::redirect("/");
Ok(())
}

View file

@ -1,3 +1,4 @@
use self::add::AddSeries;
use leptos::*;
use leptos_router::*;
use serde::{Deserialize, Serialize};
@ -10,7 +11,11 @@ pub mod view;
#[component]
pub fn SeriesList() -> impl IntoView {
let load = create_resource(|| (), |_| async move { get_all().await });
let add_user = expect_context::<Action<AddSeries, Result<(), ServerFnError>>>();
let load = create_resource(
move || add_user.version().get(),
|_| async move { get_all().await },
);
view! {
<Suspense fallback=|| view!{ <div>"Loading..."</div> }>
<ul class="list-group mb-3">
@ -55,12 +60,14 @@ pub struct Series {
#[server]
pub async fn get_all() -> Result<Vec<Series>, ServerFnError> {
use crate::db::load_statement;
use sqlx::{Pool, Postgres};
use tokio_stream::StreamExt;
let pool: Pool<Postgres> = expect_context();
let mut r = sqlx::query_as::<_, Series>("select * from series;").fetch(&pool);
let s = load_statement("select_series.sql");
let mut r = sqlx::query_as::<_, Series>(&s).fetch(&pool);
let mut found = Vec::new();
while let Some(series) = r.try_next().await? {

16
src/db.rs Normal file
View file

@ -0,0 +1,16 @@
use anyhow::format_err;
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "sql/"]
pub struct Asset;
pub fn load_statement<S: AsRef<str>>(asset: S) -> String {
let asset = asset.as_ref();
let loaded = Asset::get(asset)
.ok_or_else(|| format_err!("Could not load SQL asset, {asset}!"))
.unwrap();
String::from_utf8(loaded.data.to_vec()).expect(&format!(
"SQL asset, {asset}, could not be parsed as UTF-8!"
))
}

View file

@ -1,4 +1,6 @@
pub mod app;
#[cfg(feature = "ssr")]
pub mod db;
pub mod error_template;
#[cfg(feature = "ssr")]
pub mod fileserv;