From b2e55008ddc703ca8c63dd1e0497d2e5e99ddb48 Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Sat, 14 Sep 2024 18:33:50 -0400 Subject: [PATCH] Add ability to watch an episode - Migration for new backing table. - CRUD server functions, new components to display and interact. --- Cargo.lock | 69 +++++++++ Cargo.toml | 2 +- migrations/20240902212954_add-series.sql | 16 ++- migrations/20240907190149_add-links.sql | 4 - migrations/20240914205329_add-viewing.sql | 9 ++ sql/insert_viewing.sql | 1 + sql/select_viewings.sql | 3 + src/app/series/add.rs | 11 +- src/app/series/history.rs | 162 ++++++++++++++++++++++ src/app/series/mod.rs | 46 ++++-- src/app/series/view.rs | 37 ++--- 11 files changed, 317 insertions(+), 43 deletions(-) delete mode 100644 migrations/20240907190149_add-links.sql create mode 100644 migrations/20240914205329_add-viewing.sql create mode 100644 sql/insert_viewing.sql create mode 100644 sql/select_viewings.sql create mode 100644 src/app/series/history.rs diff --git a/Cargo.lock b/Cargo.lock index 2a481e3..7e5a77d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,21 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.15" @@ -338,6 +353,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets 0.52.6", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -445,6 +472,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.14" @@ -1049,6 +1082,29 @@ dependencies = [ "tokio", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2436,6 +2492,7 @@ dependencies = [ "atoi", "byteorder", "bytes", + "chrono", "crc", "crossbeam-queue", "either", @@ -2520,6 +2577,7 @@ dependencies = [ "bitflags", "byteorder", "bytes", + "chrono", "crc", "digest", "dotenvy", @@ -2562,6 +2620,7 @@ dependencies = [ "base64", "bitflags", "byteorder", + "chrono", "crc", "dotenvy", "etcetera", @@ -2598,6 +2657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" dependencies = [ "atoi", + "chrono", "flume", "futures-channel", "futures-core", @@ -3218,6 +3278,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 3bfdaa3..15f8392 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ wasm-bindgen = "=0.2.93" thiserror = "1" tracing = { version = "0.1", optional = true } http = "1" -sqlx = { version = "0.8.1", features = ["postgres", "runtime-tokio", "tls-rustls-ring", "uuid"], optional = true } +sqlx = { version = "0.8.1", features = ["postgres", "runtime-tokio", "tls-rustls-ring", "uuid", "chrono"], optional = true } anyhow = "1.0.86" log = { version = "0.4.22", optional = true } env_logger = { version = "0.11.5", optional = true } diff --git a/migrations/20240902212954_add-series.sql b/migrations/20240902212954_add-series.sql index 5cae972..0503f7b 100644 --- a/migrations/20240902212954_add-series.sql +++ b/migrations/20240902212954_add-series.sql @@ -1,6 +1,12 @@ -create table if not exists "public"."series" ( - "id" uuid default gen_random_uuid() not null primary key, - "name" text not null, - "created" timestamptz default now() not null, - "updated" timestamptz default now() not null +create table if not exists series ( + id uuid default gen_random_uuid() not null primary key, + created timestamptz default now() not null, + updated timestamptz default now() not null, + name text not null, + source text not null check (source in ( + 'Disney', 'Hulu', 'Paramount', 'Prime', 'Max', 'Netflix', 'Shudder' + )), + source_url text not null, + imdb text null, + wikipedia text null ); diff --git a/migrations/20240907190149_add-links.sql b/migrations/20240907190149_add-links.sql deleted file mode 100644 index 3e40a46..0000000 --- a/migrations/20240907190149_add-links.sql +++ /dev/null @@ -1,4 +0,0 @@ -alter table "public"."series" add column source text not null; -alter table "public"."series" add column source_url text not null; -alter table "public"."series" add column imdb text null; -alter table "public"."series" add column wikipedia text null diff --git a/migrations/20240914205329_add-viewing.sql b/migrations/20240914205329_add-viewing.sql new file mode 100644 index 0000000..028493d --- /dev/null +++ b/migrations/20240914205329_add-viewing.sql @@ -0,0 +1,9 @@ +create table if not exists viewing ( + id uuid default gen_random_uuid() not null primary key, + series_id uuid not null references series(id), + created timestamptz default now() not null, + updated timestamptz default now() not null, + season smallint not null check (season > 0), + episode smallint not null check (episode > 0), + "comment" text null +); diff --git a/sql/insert_viewing.sql b/sql/insert_viewing.sql new file mode 100644 index 0000000..eb12954 --- /dev/null +++ b/sql/insert_viewing.sql @@ -0,0 +1 @@ +insert into viewing (series_id, season, episode, "comment") values ($1, $2, $3, $4); diff --git a/sql/select_viewings.sql b/sql/select_viewings.sql new file mode 100644 index 0000000..cc03f91 --- /dev/null +++ b/sql/select_viewings.sql @@ -0,0 +1,3 @@ +select * +from viewing +where series_id = $1; diff --git a/src/app/series/add.rs b/src/app/series/add.rs index 4d02f08..06105c7 100644 --- a/src/app/series/add.rs +++ b/src/app/series/add.rs @@ -79,12 +79,17 @@ pub async fn add_series( imdb: String, wikipedia: String, ) -> Result<(), ServerFnError> { - use crate::db::load_statement; + use std::sync::OnceLock; + use sqlx::{Pool, Postgres}; + + use crate::db::load_statement; + let pool = expect_context::>(); - let s = load_statement("insert_series.sql"); - sqlx::query(&s) + static SQL: OnceLock = OnceLock::new(); + let s = SQL.get_or_init(|| load_statement("insert_series.sql")); + sqlx::query(s) .persistent(true) .bind(name) .bind(source.to_string()) diff --git a/src/app/series/history.rs b/src/app/series/history.rs new file mode 100644 index 0000000..32c23f7 --- /dev/null +++ b/src/app/series/history.rs @@ -0,0 +1,162 @@ +use leptos::*; +use leptos_router::*; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use super::format_errors; + +#[component] +pub fn ViewingList(series_id: Uuid) -> impl IntoView { + let add = create_server_action::(); + let viewings = create_resource( + move || (add.version().get(), series_id), + |(_, id)| async move { get_viewings(id).await }, + ); + view! { +

Viewing History

+ Loading... }> + {viewings().map(format_viewings)} + + + +
+
+ +
+
+
+ + + + +
+
+ +