fix routes page
This commit is contained in:
parent
aebd30c1c2
commit
a6942156e4
@ -2,9 +2,18 @@ use crate::models::HoldRole;
|
||||
use crate::models::{self};
|
||||
use leptos::prelude::*;
|
||||
|
||||
/// Displays a grid of the problem
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn Problem(#[prop(into)] dim: Signal<models::WallDimensions>, #[prop(into)] problem: Signal<models::Problem>) -> impl IntoView {
|
||||
pub fn Problem(
|
||||
/// Wall dimensions
|
||||
#[prop(into)]
|
||||
dim: Signal<models::WallDimensions>,
|
||||
|
||||
/// Problem (route)
|
||||
#[prop(into)]
|
||||
problem: Signal<models::Problem>,
|
||||
) -> impl IntoView {
|
||||
let holds = move || {
|
||||
let mut holds = vec![];
|
||||
for row in 0..dim.get().rows {
|
||||
|
29
crates/ascend/src/components/problem_info.rs
Normal file
29
crates/ascend/src/components/problem_info.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::models;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn ProblemInfo(problem: models::Problem) -> impl IntoView {
|
||||
tracing::trace!("Enter problem info");
|
||||
|
||||
let name = problem.name;
|
||||
let set_by = problem.set_by;
|
||||
let method = problem.method;
|
||||
|
||||
view! {
|
||||
<div class="grid grid-rows-none grid-cols-[auto,1fr]">
|
||||
<NameValue name="Name:" value=name />
|
||||
<NameValue name="Method:" value=method.to_string() />
|
||||
<NameValue name="Set By:" value=set_by />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn NameValue(#[prop(into)] name: String, #[prop(into)] value: String) -> impl IntoView {
|
||||
view! {
|
||||
<p class="text-orange-300 mr-4">{name}</p>
|
||||
<p class="text-white font-semibold">{value}</p>
|
||||
}
|
||||
}
|
@ -2,16 +2,19 @@ pub mod app;
|
||||
pub mod pages {
|
||||
pub mod edit_wall;
|
||||
pub mod routes;
|
||||
pub mod settings;
|
||||
pub mod wall;
|
||||
}
|
||||
pub mod components {
|
||||
pub use button::Button;
|
||||
pub use header::StyledHeader;
|
||||
pub use problem::Problem;
|
||||
pub use problem_info::ProblemInfo;
|
||||
|
||||
pub mod button;
|
||||
pub mod header;
|
||||
pub mod problem;
|
||||
pub mod problem_info;
|
||||
}
|
||||
pub mod resources {
|
||||
use crate::codec::ron::Ron;
|
||||
|
@ -22,7 +22,6 @@ pub mod v2 {
|
||||
use serde::Serialize;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Root {
|
||||
|
@ -37,7 +37,7 @@ pub fn Routes() -> impl IntoView {
|
||||
link: Some("/".to_string()),
|
||||
}],
|
||||
middle: vec![HeaderItem {
|
||||
text: "ROUTES".to_string(),
|
||||
text: "Routes".to_string(),
|
||||
link: None,
|
||||
}],
|
||||
right: vec![],
|
||||
@ -64,7 +64,7 @@ pub fn Routes() -> impl IntoView {
|
||||
each=problems_sample
|
||||
key=|problem| problem.uid
|
||||
children=move |problem: models::Problem| {
|
||||
view! { <Problem dim=wall_dimensions problem /> }
|
||||
view! { <Problem dim=wall_dimensions problem /> <hr class="h-px my-8 border-0 bg-gray-700" />}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
@ -76,11 +76,10 @@ pub fn Routes() -> impl IntoView {
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class="min-w-screen min-h-screen bg-slate-900">
|
||||
<div class="min-w-screen min-h-screen bg-neutral-950">
|
||||
<StyledHeader items=header_items />
|
||||
|
||||
<div class="container mx-auto mt-2">
|
||||
{move || view! { <Import wall_uid=wall_uid.get() /> }}
|
||||
<div class="container mx-auto mt-6">
|
||||
<Suspense fallback=|| view! { <p>"loading"</p> }>{suspend}</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
@ -90,44 +89,12 @@ pub fn Routes() -> impl IntoView {
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn Problem(#[prop(into)] dim: Signal<models::WallDimensions>, #[prop(into)] problem: Signal<models::Problem>) -> impl IntoView {
|
||||
tracing::debug!("Enter");
|
||||
|
||||
view! {
|
||||
<div class="flex items-start">
|
||||
<div class="flex-none">
|
||||
<components::Problem dim problem />
|
||||
<p>{move || problem.get().name.clone()}</p>
|
||||
</div>
|
||||
<components::ProblemInfo problem=problem.get() />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn Import(wall_uid: WallUid) -> impl IntoView {
|
||||
tracing::debug!("ready");
|
||||
|
||||
let import_from_mini_moonboard = Action::from(ServerAction::<ImportFromMiniMoonboard>::new());
|
||||
|
||||
let onclick = move |_mouse_event| {
|
||||
import_from_mini_moonboard.dispatch(ImportFromMiniMoonboard { wall_uid });
|
||||
};
|
||||
|
||||
view! {
|
||||
<p>"Import problems from"</p>
|
||||
<button on:click=onclick>"Mini Moonboard"</button>
|
||||
}
|
||||
}
|
||||
|
||||
#[server(name = ImportFromMiniMoonboard)]
|
||||
#[tracing::instrument]
|
||||
async fn import_from_mini_moonboard(wall_uid: WallUid) -> Result<(), ServerFnError> {
|
||||
use crate::server::config::Config;
|
||||
use crate::server::db::Database;
|
||||
|
||||
tracing::info!("Importing mini moonboard problems");
|
||||
|
||||
let config = expect_context::<Config>();
|
||||
let db = expect_context::<Database>();
|
||||
|
||||
crate::server::operations::import_mini_moonboard_problems(&config, db, wall_uid).await?;
|
||||
|
||||
// TODO: Return information about what was done
|
||||
Ok(())
|
||||
}
|
||||
|
63
crates/ascend/src/pages/settings.rs
Normal file
63
crates/ascend/src/pages/settings.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use crate::components::StyledHeader;
|
||||
use crate::components::header::HeaderItem;
|
||||
use crate::components::header::HeaderItems;
|
||||
use crate::models::WallUid;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub fn Settings() -> impl IntoView {
|
||||
let header_items = HeaderItems {
|
||||
left: vec![HeaderItem {
|
||||
text: "← Ascend".to_string(),
|
||||
link: Some("/".to_string()),
|
||||
}],
|
||||
middle: vec![HeaderItem {
|
||||
text: "Settings".to_string(),
|
||||
link: None,
|
||||
}],
|
||||
right: vec![],
|
||||
};
|
||||
|
||||
view! {
|
||||
<div class="min-w-screen min-h-screen bg-neutral-950">
|
||||
<StyledHeader items=header_items />
|
||||
|
||||
<div class="container mx-auto mt-2">
|
||||
// {move || view! { <Import wall_uid=wall_uid.get() /> }}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn Import(wall_uid: WallUid) -> impl IntoView {
|
||||
let import_from_mini_moonboard = Action::from(ServerAction::<ImportFromMiniMoonboard>::new());
|
||||
|
||||
let onclick = move |_mouse_event| {
|
||||
import_from_mini_moonboard.dispatch(ImportFromMiniMoonboard { wall_uid });
|
||||
};
|
||||
|
||||
view! {
|
||||
<p>"Import problems from"</p>
|
||||
<button on:click=onclick>"Mini Moonboard"</button>
|
||||
}
|
||||
}
|
||||
|
||||
#[server(name = ImportFromMiniMoonboard)]
|
||||
#[tracing::instrument]
|
||||
async fn import_from_mini_moonboard(wall_uid: WallUid) -> Result<(), ServerFnError> {
|
||||
use crate::server::config::Config;
|
||||
use crate::server::db::Database;
|
||||
|
||||
tracing::info!("Importing mini moonboard problems");
|
||||
|
||||
let config = expect_context::<Config>();
|
||||
let db = expect_context::<Database>();
|
||||
|
||||
crate::server::operations::import_mini_moonboard_problems(&config, db, wall_uid).await?;
|
||||
|
||||
// TODO: Return information about what was done
|
||||
Ok(())
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
// TODO: Put current problem UID in url
|
||||
|
||||
use crate::codec::ron::RonEncoded;
|
||||
use crate::components::ProblemInfo;
|
||||
use crate::components::button::Button;
|
||||
use crate::components::header::HeaderItem;
|
||||
use crate::components::header::HeaderItems;
|
||||
@ -168,30 +169,3 @@ fn Hold(hold: models::Hold, role: Signal<Option<HoldRole>>) -> impl IntoView {
|
||||
tracing::trace!("view");
|
||||
view! { <div class=class>{img}</div> }
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn ProblemInfo(problem: models::Problem) -> impl IntoView {
|
||||
tracing::trace!("Enter problem info");
|
||||
|
||||
let name = problem.name;
|
||||
let set_by = problem.set_by;
|
||||
let method = problem.method;
|
||||
|
||||
view! {
|
||||
<div class="grid grid-cols-[auto,1fr] gap-2">
|
||||
<NameValue name="Name:" value=name />
|
||||
<NameValue name="Method:" value=method.to_string() />
|
||||
<NameValue name="Set By:" value=set_by />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn NameValue(#[prop(into)] name: String, #[prop(into)] value: String) -> impl IntoView {
|
||||
view! {
|
||||
<p class="text-orange-300">{name}</p>
|
||||
<p class="text-white">{value}</p>
|
||||
}
|
||||
}
|
||||
|
6
todo.md
6
todo.md
@ -1,5 +1,3 @@
|
||||
- save images with a uuid
|
||||
- downscale images
|
||||
- associate routes with wall
|
||||
- group routes by pattern (pattern family has shift/mirror variations)
|
||||
- generate pattern families of variations when importing problems
|
||||
@ -10,3 +8,7 @@
|
||||
- use wall id in URL.
|
||||
- decide on routes vs problems terminology
|
||||
- decide on holds vs wall-edit terminology
|
||||
- clock
|
||||
- hotkeys (enter =next problem, arrow = shift left/right up/down)
|
||||
- remove brightness reduction when mousing over holds
|
||||
- impl `sizes` hint next to `srcset`
|
||||
|
Loading…
x
Reference in New Issue
Block a user