Updated UI once more to allow for multiple sub-tabs
This commit is contained in:
@@ -79,13 +79,62 @@ pub fn demo() -> impl leptos::IntoView {
|
|||||||
<h2>Demo - { id } - { map }</h2>
|
<h2>Demo - { id } - { map }</h2>
|
||||||
|
|
||||||
<button on:click=move |_| rerun_analysis.dispatch(())>Rerun analysis</button>
|
<button on:click=move |_| rerun_analysis.dispatch(())>Rerun analysis</button>
|
||||||
<div class="analysis_bar">
|
<TabBar prefix=move || format!("/demo/{}/", id()) parts=&[("scoreboard", "Scoreboard"), ("perround", "Per Round"), ("heatmaps", "Heatmaps")] />
|
||||||
<div class="analysis_selector" class:current=move || selected_tab() == "scoreboard"><A href="scoreboard"><span>Scoreboard</span></A></div>
|
|
||||||
<div class="analysis_selector" class:current=move || selected_tab() == "perround"><A href="perround"><span>Per Round</span></A></div>
|
|
||||||
<div class="analysis_selector" class:current=move || selected_tab() == "heatmaps"><A href="heatmaps"><span>Heatmaps</span></A></div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<Outlet/>
|
<Outlet/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[leptos::component]
|
||||||
|
pub fn tab_bar<P>(prefix: P, parts: &'static [(&'static str, &'static str)]) -> impl leptos::IntoView where P: Fn() -> String + Copy + 'static {
|
||||||
|
let selected_tab = move || {
|
||||||
|
let prefix = prefix();
|
||||||
|
let loc = leptos_router::use_location();
|
||||||
|
let loc_path = loc.pathname.get();
|
||||||
|
let trailing = loc_path.strip_prefix(&prefix).unwrap_or(&loc_path).split('/').filter(|l| !l.is_empty()).next();
|
||||||
|
trailing.or(parts.first().map(|p| p.0)).unwrap_or("").to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
let style = stylers::style! {
|
||||||
|
"Demo",
|
||||||
|
.analysis_bar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(var(--rows), auto);
|
||||||
|
column-gap: 20px;
|
||||||
|
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.analysis_selector {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
padding: 1vw 1vh;
|
||||||
|
color: #d5d5d5;
|
||||||
|
background-color: #4d4d4d;
|
||||||
|
}
|
||||||
|
.current {
|
||||||
|
background-color: #5d5d5d;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let tabs = move || parts.into_iter().map(|(routename, name)| {
|
||||||
|
view! {class=style,
|
||||||
|
<div class="analysis_selector" class:current=move || selected_tab() == routename.to_string()>
|
||||||
|
<A href=routename.to_string()>
|
||||||
|
<span>{ name.to_string() }</span>
|
||||||
|
</A>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
view! {class = style,
|
||||||
|
<div class="analysis_bar" style=format!("--rows: {}", parts.len())>
|
||||||
|
{ tabs }
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,46 +1,20 @@
|
|||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
use leptos_router::Outlet;
|
||||||
|
|
||||||
|
pub mod general;
|
||||||
|
pub mod utility;
|
||||||
|
|
||||||
|
use crate::demo::TabBar;
|
||||||
|
|
||||||
#[leptos::component]
|
#[leptos::component]
|
||||||
pub fn scoreboard() -> impl leptos::IntoView {
|
pub fn scoreboard() -> impl leptos::IntoView {
|
||||||
use leptos::Suspense;
|
let params = leptos_router::use_params_map();
|
||||||
|
let id = move || params.with(|params| params.get("id").cloned().unwrap_or_default());
|
||||||
let scoreboard_resource =
|
|
||||||
create_resource(leptos_router::use_params_map(), |params| async move {
|
|
||||||
let id = params.get("id").unwrap();
|
|
||||||
|
|
||||||
let res =
|
|
||||||
reqwasm::http::Request::get(&format!("/api/demos/{}/analysis/scoreboard", id))
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
res.json::<common::demo_analysis::ScoreBoard>()
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
let (ordering, set_ordering) = create_signal::<orderings::Ordering>(orderings::DAMAGE);
|
|
||||||
|
|
||||||
let scoreboards = move || {
|
|
||||||
scoreboard_resource
|
|
||||||
.get()
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|v| v.teams.into_iter())
|
|
||||||
.map(|team| {
|
|
||||||
view! {
|
|
||||||
<TeamScoreboard value=team.players team_name=format!("Team {} - {}", team.number, team.score) />
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<h2>Scoreboard</h2>
|
<TabBar prefix=move || format!("/demo/{}/scoreboard", id()) parts=&[("general", "General"), ("utility", "Utility")] />
|
||||||
|
|
||||||
<Suspense
|
<Outlet />
|
||||||
fallback=move || view! { <p>Loading Scoreboard data</p> }
|
|
||||||
>
|
|
||||||
{ scoreboards }
|
|
||||||
</Suspense>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
frontend/src/demo/scoreboard/general.rs
Normal file
45
frontend/src/demo/scoreboard/general.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[leptos::component]
|
||||||
|
pub fn general() -> impl leptos::IntoView {
|
||||||
|
use leptos::Suspense;
|
||||||
|
|
||||||
|
let scoreboard_resource =
|
||||||
|
create_resource(leptos_router::use_params_map(), |params| async move {
|
||||||
|
let id = params.get("id").unwrap();
|
||||||
|
|
||||||
|
let res =
|
||||||
|
reqwasm::http::Request::get(&format!("/api/demos/{}/analysis/scoreboard", id))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
res.json::<common::demo_analysis::ScoreBoard>()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
let (ordering, set_ordering) = create_signal::<orderings::Ordering>(orderings::DAMAGE);
|
||||||
|
|
||||||
|
let scoreboards = move || {
|
||||||
|
scoreboard_resource
|
||||||
|
.get()
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|v| v.teams.into_iter())
|
||||||
|
.map(|team| {
|
||||||
|
view! {
|
||||||
|
<TeamScoreboard value=team.players team_name=format!("Team {} - {}", team.number, team.score) />
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<Suspense
|
||||||
|
fallback=move || view! { <p>Loading Scoreboard data</p> }
|
||||||
|
>
|
||||||
|
{ scoreboards }
|
||||||
|
</Suspense>
|
||||||
|
}
|
||||||
|
}
|
||||||
8
frontend/src/demo/scoreboard/utility.rs
Normal file
8
frontend/src/demo/scoreboard/utility.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[leptos::component]
|
||||||
|
pub fn utility() -> impl leptos::IntoView {
|
||||||
|
view! {
|
||||||
|
Utility
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,8 +20,12 @@ fn main() {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" view=move || view! { <Homepage get_notification=get_reload_demos /> } />
|
<Route path="/" view=move || view! { <Homepage get_notification=get_reload_demos /> } />
|
||||||
<Route path="/demo/:id" view=Demo>
|
<Route path="/demo/:id" view=Demo>
|
||||||
|
<Route path="scoreboard" view=frontend::demo::scoreboard::Scoreboard>
|
||||||
|
<Route path="general" view=frontend::demo::scoreboard::general::General />
|
||||||
|
<Route path="utility" view=frontend::demo::scoreboard::utility::Utility />
|
||||||
|
<Route path="" view=frontend::demo::scoreboard::general::General />
|
||||||
|
</Route>
|
||||||
<Route path="perround" view=frontend::demo::perround::PerRound />
|
<Route path="perround" view=frontend::demo::perround::PerRound />
|
||||||
<Route path="scoreboard" view=frontend::demo::scoreboard::Scoreboard />
|
|
||||||
<Route path="heatmaps" view=frontend::demo::heatmap::Heatmaps />
|
<Route path="heatmaps" view=frontend::demo::heatmap::Heatmaps />
|
||||||
<Route path="" view=frontend::demo::scoreboard::Scoreboard />
|
<Route path="" view=frontend::demo::scoreboard::Scoreboard />
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
Reference in New Issue
Block a user