diff --git a/crates/ascend/Cargo.toml b/crates/ascend/Cargo.toml
index 001f12b..b8c9e90 100644
--- a/crates/ascend/Cargo.toml
+++ b/crates/ascend/Cargo.toml
@@ -15,7 +15,12 @@ chrono = { version = "0.4.39", features = ["now", "serde"] }
clap = { version = "4.5.7", features = ["derive"] }
confik = { version = "0.12", optional = true, features = ["camino"] }
console_error_panic_hook = "0.1"
-derive_more = { version = "1", features = ["display", "error", "from"] }
+derive_more = { version = "1", features = [
+ "display",
+ "error",
+ "from",
+ "from_str",
+] }
http = "1"
leptos = { version = "0.7.4", features = ["tracing"] }
leptos_axum = { version = "0.7", optional = true }
diff --git a/crates/ascend/src/app.rs b/crates/ascend/src/app.rs
index 298eed8..4cd293a 100644
--- a/crates/ascend/src/app.rs
+++ b/crates/ascend/src/app.rs
@@ -1,7 +1,10 @@
+use crate::codec::ron::RonCodec;
+use crate::models;
use crate::pages;
use leptos::prelude::*;
use leptos_router::components::*;
use leptos_router::path;
+use std::sync::Arc;
pub fn shell(options: LeptosOptions) -> impl IntoView {
use leptos_meta::MetaTags;
@@ -39,13 +42,67 @@ pub fn App() -> impl leptos::IntoView {
-
-
-
-
-
-
-
+
+
+
+
+
+
}
}
+
+#[component]
+pub fn Home() -> impl leptos::IntoView {
+ // TODO: show cards with walls, and a "new wall" button
+
+ tracing::debug!("Rendering home component");
+
+ let action = Action::new(|()| async move {
+ tracing::debug!("running action");
+ let walls = get_walls().await.unwrap().into_inner();
+ let wall = walls.first();
+
+ if let Some(wall) = wall {
+ let navigate = leptos_router::hooks::use_navigate();
+ let url = format!("/wall/{}", wall.uid);
+ navigate(&url, Default::default());
+ }
+ });
+
+ tracing::debug!("dispatching action...");
+
+ action.dispatch(());
+
+ tracing::debug!("dispatched action");
+
+ leptos::view! {}
+}
+
+#[server]
+#[tracing::instrument(skip_all, err)]
+async fn get_walls() -> Result>, ServerFnError> {
+ use redb::ReadableTable;
+
+ tracing::debug!("get walls");
+
+ let db = expect_context::>();
+ tracing::debug!("got db from context");
+
+ let walls = tokio::task::spawn_blocking(move || -> Result, ServerFnError> {
+ tracing::debug!("beginning read transaction");
+ let read_txn = db.begin_read()?;
+
+ tracing::debug!("opening table");
+ let walls_table = read_txn.open_table(crate::server::db::current::TABLE_WALLS)?;
+ tracing::debug!("opened table");
+ let walls: Vec = walls_table.iter()?.map(|r| r.map(|(_, v)| v.value())).collect::>()?;
+
+ tracing::debug!("got walls {walls:?}");
+
+ Ok(walls)
+ })
+ .await??;
+
+ Ok(RonCodec::new(walls))
+}
diff --git a/crates/ascend/src/models.rs b/crates/ascend/src/models.rs
index e568a9c..728c940 100644
--- a/crates/ascend/src/models.rs
+++ b/crates/ascend/src/models.rs
@@ -6,10 +6,10 @@ pub use v1::HoldRole;
pub use v1::Image;
pub use v2::Method;
pub use v2::Problem;
-pub use v2::ProblemId;
+pub use v2::ProblemUid;
pub use v2::Root;
pub use v2::Wall;
-pub use v2::WallId;
+pub use v2::WallUid;
pub mod v2 {
use super::v1;
@@ -20,21 +20,21 @@ pub mod v2 {
#[derive(Serialize, Deserialize, Debug)]
pub struct Root {
- pub walls: BTreeSet,
+ pub walls: BTreeSet,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Wall {
- pub uid: WallId,
+ pub uid: WallUid,
pub rows: u64,
pub cols: u64,
pub holds: BTreeMap,
- pub problems: BTreeSet,
+ pub problems: BTreeSet,
}
- #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
- pub struct WallId(pub uuid::Uuid);
- impl WallId {
+ #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, derive_more::FromStr, derive_more::Display)]
+ pub struct WallUid(pub uuid::Uuid);
+ impl WallUid {
pub fn new() -> Self {
Self(uuid::Uuid::new_v4())
}
@@ -42,7 +42,7 @@ pub mod v2 {
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Problem {
- pub uid: ProblemId,
+ pub uid: ProblemUid,
pub name: String,
pub set_by: String,
pub holds: BTreeMap,
@@ -51,8 +51,8 @@ pub mod v2 {
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
- pub struct ProblemId(pub uuid::Uuid);
- impl ProblemId {
+ pub struct ProblemUid(pub uuid::Uuid);
+ impl ProblemUid {
pub fn new() -> Self {
Self(uuid::Uuid::new_v4())
}
diff --git a/crates/ascend/src/pages/wall.rs b/crates/ascend/src/pages/wall.rs
index 61d49e6..6264157 100644
--- a/crates/ascend/src/pages/wall.rs
+++ b/crates/ascend/src/pages/wall.rs
@@ -5,19 +5,32 @@ use crate::components::header::HeaderItems;
use crate::components::header::StyledHeader;
use crate::models;
use crate::models::HoldRole;
+use leptos::Params;
use leptos::prelude::*;
use leptos::reactive::graph::ReactiveNode;
-use serde::Deserialize;
-use serde::Serialize;
-use std::ops::Deref;
+use leptos_router::params::Params;
use std::sync::Arc;
+#[derive(Params, PartialEq, Clone)]
+struct WallParams {
+ id: Option,
+}
+
#[component]
pub fn Wall() -> impl leptos::IntoView {
- let load = async move {
- // TODO: What to do about this unwrap?
- load_initial_data().await.unwrap()
- };
+ let params = leptos_router::hooks::use_params::();
+
+ let wall = Resource::new(
+ move || params.get().unwrap().id,
+ move |wall_id| async move {
+ if let Some(wall_id) = wall_id {
+ let wall = get_wall(wall_id).await.unwrap().into_inner();
+ Some(wall)
+ } else {
+ None
+ }
+ },
+ );
let header_items = HeaderItems {
left: vec![],
@@ -38,20 +51,27 @@ pub fn Wall() -> impl leptos::IntoView {
};
leptos::view! {
-
-
+
+
-
-
-
-
+
+ "Loading..."}>
+ {move || Suspend::new(async move{
+ let wall: Option
+
-
- }
+ }
}
#[component]
-fn Ready(data: InitialData) -> impl leptos::IntoView {
+fn Ready(wall: models::Wall) -> impl leptos::IntoView {
tracing::debug!("ready");
let (current_problem, current_problem_writer) = signal(None::
);
@@ -65,7 +85,7 @@ fn Ready(data: InitialData) -> impl leptos::IntoView {
});
let mut cells = vec![];
- for (&hold_position, hold) in &data.wall.holds {
+ for (&hold_position, hold) in &wall.holds {
let role = move || current_problem.get().and_then(|problem| problem.holds.get(&hold_position).copied());
let role = Signal::derive(role);
@@ -73,7 +93,7 @@ fn Ready(data: InitialData) -> impl leptos::IntoView {
cells.push(cell);
}
- let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-3", data.wall.rows, data.wall.cols);
+ let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-3", wall.rows, wall.cols);
view! {
@@ -120,20 +140,15 @@ fn Hold(hold: models::Hold, #[prop(into)] role: Signal