flams_router_content/
components.rs1#![allow(clippy::must_use_candidate)]
2
3use flams_router_base::maybe_lazy;
4use flams_web_utils::{client_only, components::wait_and_then_fn};
5use ftml_components::{
6 SidebarPosition,
7 components::{content::FtmlViewable, terms::inject_comp_css},
8};
9use ftml_dom::{DocumentState, FtmlViews, toc::TocSource, utils::css::CssExt};
10use ftml_uris::{
11 DocumentUri, Uri, UriKind,
12 components::{
13 DocumentUriComponentTuple, DocumentUriComponents, UriComponentTuple, UriComponents,
14 UriComponentsTrait,
15 },
16};
17use leptos::prelude::*;
18use leptos_router::hooks::use_query_map;
19
20maybe_lazy!(
21 TopDocRouter = {
22 let params = use_query_map().get_untracked();
23 if let Some(p) = params.get_str("uri") {
24 let Ok(uri) = <ftml_uris::Uri as std::str::FromStr>::from_str(p) else {
25 return view! { <leptos_router::components::Redirect path="/dashboard"/> }
26 .into_any();
27 };
28 DocumentOfTop(DocumentOfTopProps { uri }).into_any()
29 } else {
30 view! { <leptos_router::components::Redirect path="/dashboard"/> }.into_any()
31 }
32 }
33);
34
35maybe_lazy!(
36 UriTopRouter = {
37 let works = use_query_map()
38 .with_untracked(|p| p.get_str("a").is_some() || p.get_str("uri").is_some());
39 if works {
40 URITop()
41 } else {
42 view! { <leptos_router::components::Redirect path="/dashboard"/> }.into_any()
43 }
44 }
45);
46
47#[component(transparent)]
48pub fn URITop() -> AnyView {
49 ftml_dom::global_setup(move || {
51 crate::Views::top(move || {
52 use_query_map().with_untracked(|m| {
53 if let Ok(doc) = m.as_document() {
54 return view!(<Document doc=doc.into()/>).into_any();
55 }
56 let kind = match m.kind() {
57 Ok(k) => k,
58 Err(e) => {
59 return flams_web_utils::components::display_error(
60 format!("Invalid URI: {e}").into(),
61 )
62 .into_any();
63 }
64 };
65 let comps = match m.as_comps() {
66 Ok(k) => k,
67 Err(e) => {
68 return flams_web_utils::components::display_error(
69 format!("Invalid URI: {e}").into(),
70 )
71 .into_any();
72 }
73 };
74 match kind {
75 UriKind::Base => {
76 view! { <leptos_router::components::Redirect path="/dashboard"/> }
77 .into_any()
78 }
79 UriKind::Document =>
80 {
82 flams_web_utils::components::display_error("Invalid URI".into()).into_any()
83 }
84 UriKind::DocumentElement | UriKind::Symbol => {
85 view!(<Fragment uri=comps.into() position=SidebarPosition::Next/>)
86 .into_any()
87 }
88 UriKind::Module => {
89 let comps: UriComponents = comps.into();
90 client_only!(view!(<DoModule comps=comps.clone()/>)).into_any()
91 }
92 UriKind::Archive | UriKind::Path => {
93 let comps: UriComponents = comps.into();
94 client_only!(
95 view!(<super::archive_views::ArchiveView comps = comps.clone() />)
96 )
97 .into_any()
98 }
99 }
100 })
101 })
102 })
103 .into_any()
104}
105
106#[component]
107fn DoModule(comps: UriComponents) -> impl IntoView {
108 let comps = UriComponentTuple::from(comps);
109 let uri = if let Some(Uri::Module(uri)) = comps.uri {
110 Some(uri)
111 } else {
112 None
113 };
114 let a = comps.a;
115 let p = comps.p;
116 let m = comps.m;
117 inject_comp_css();
118 wait_and_then_fn(
119 move || crate::server_fns::get_module(uri.clone(), a.clone(), p.clone(), m.clone()),
120 |r| DocumentState::no_document(move || r.as_view()),
121 )
122}
123
124#[component]
125pub fn DocumentOfTop(uri: Uri) -> AnyView {
126 use leptos_router::components::Redirect;
127 client_only!({
128 let uri = uri.clone();
129 wait_and_then_fn(
130 move || super::server_fns::document_of(uri.clone()),
131 |u| {
132 view!(<Redirect path=format!("/?uri={}",urlencoding::encode(&u.to_string()))/>)
133 .into_any()
134 },
135 )
136 })
137 .into_any()
138}
139
140#[component]
141pub fn Fragment(uri: UriComponents, position: SidebarPosition) -> AnyView {
142 use ftml_dom::utils::css::CssExt;
143 let f = move || UriComponentTuple::from(uri).apply1(super::server_fns::fragment, None);
144 client_only!({
145 ftml_components::utils::wait_and_then(
146 f.clone(),
147 move |(uri, css, html)| {
148 for css in css {
149 css.inject();
150 }
151 let (uri, src) = match uri {
152 Uri::Document(d) => {
153 (Some(d.into()), TocSource::Get)
155 }
156 Uri::DocumentElement(d) => {
157 (Some(d.into()), TocSource::None)
159 }
160 _ => {
161 (None, TocSource::None)
163 }
164 };
165 crate::Views::render_fragment(uri, position, true, src, move || {
166 crate::Views::render_ftml(html.into_string(), None).into_any()
167 })
168 },
169 |e| view!(<span style="color:red">{e.to_string()}</span>).into_any(),
170 )
171 })
172 .into_any()
173 }
175
176#[component]
177pub fn Document(doc: DocumentUriComponents) -> AnyView {
178 client_only!({
179 let doc = doc.clone();
180 ftml_components::utils::wait_and_then(
181 move || DocumentUriComponentTuple::from(doc).apply(super::server_fns::document),
182 move |(uri, css, html)| {
183 for c in css {
184 c.inject();
185 }
186 {
187 crate::Views::setup_document(
189 uri,
190 SidebarPosition::Next,
191 true,
192 TocSource::Get,
193 move || crate::Views::render_ftml(html.into_string(), None).into_any(),
194 )
195 }
196 .into_any()
197 },
198 |e| view!(<span style="color:red">{e.to_string()}</span>).into_any(),
199 )
200 })
201 .into_any()
202}
203
204#[component]
205pub fn DocumentInner(doc: DocumentUriComponents) -> AnyView {
206 let doc: UriComponents = doc.into();
207 wait_and_then_fn(
208 move || UriComponentTuple::from(doc.clone()).apply1(super::server_fns::fragment, None),
209 move |(uri, css, html)| {
210 for css in css {
211 css.inject();
212 }
213 view! {<div>{
214 crate::Views::setup_document(
215 DocumentUri::no_doc().clone(),
216 SidebarPosition::None,
217 true,
218 TocSource::None,
219 move || crate::Views::render_ftml(html.into_string(),None).into_any()
220 )
221 }</div>}
222 .into_any()
223 },
224 )
225 .into_any()
226}