mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-22 19:40:14 -04:00
Fixup SSR and links
This commit is contained in:
parent
856fac5ece
commit
c9bcfe220e
@ -73,14 +73,23 @@ where
|
|||||||
async fn ui_assets(Path(path): Path<String>) -> impl IntoResponse {
|
async fn ui_assets(Path(path): Path<String>) -> impl IntoResponse {
|
||||||
info!("Serving ui path");
|
info!("Serving ui path");
|
||||||
|
|
||||||
let mut path = path.trim_start_matches("/");
|
let path = path.trim_start_matches("/");
|
||||||
path = if path == "" { "index.html" } else { path };
|
|
||||||
debug!(path = path, "Serving transformed path");
|
debug!(path = path, "Serving transformed path");
|
||||||
let file = StaticFile(path.to_owned());
|
let file = StaticFile(path.to_owned());
|
||||||
|
// TODO(jwall): We need to construct the entire html page here.
|
||||||
|
// not just this split form.
|
||||||
if file.exists() {
|
if file.exists() {
|
||||||
file.into_response()
|
file.into_response()
|
||||||
} else {
|
} else {
|
||||||
kitchen_wasm::render_to_string(path).into_response()
|
let index = UiAssets::get("index.html").expect("Unexpectedly can't find index.html");
|
||||||
|
let body = boxed(Full::from(
|
||||||
|
String::from_utf8_lossy(index.data.as_ref())
|
||||||
|
.replace("%kitchen-wasm", &kitchen_wasm::render_to_string(path)),
|
||||||
|
));
|
||||||
|
Response::builder()
|
||||||
|
.header(header::CONTENT_TYPE, "text/html")
|
||||||
|
.body(body)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main"></div>
|
<div id="main">%kitchen-wasm</div>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import init, { } from './kitchen_wasm.js';
|
import init, { } from './kitchen_wasm.js';
|
||||||
|
|
||||||
|
@ -20,14 +20,11 @@ mod web;
|
|||||||
|
|
||||||
use router_integration::DeriveRoute;
|
use router_integration::DeriveRoute;
|
||||||
use sycamore::prelude::*;
|
use sycamore::prelude::*;
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
use tracing_browser_subscriber;
|
use tracing_browser_subscriber;
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
use web::UI;
|
use web::UI;
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[wasm_bindgen(start)]
|
#[wasm_bindgen(start)]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
@ -36,11 +33,11 @@ pub fn main() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.document()
|
.document()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.query_selector("#sycamore")
|
.query_selector("#main")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
sycamore::hydrate_to(|| view! { UI() }, &root);
|
sycamore::hydrate_to(|| view! { UI(None) }, &root);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
@ -48,5 +45,5 @@ pub fn render_to_string(path: &str) -> String {
|
|||||||
use app_state::AppRoutes;
|
use app_state::AppRoutes;
|
||||||
|
|
||||||
let route = <AppRoutes as DeriveRoute>::from(&(String::new(), path.to_owned(), String::new()));
|
let route = <AppRoutes as DeriveRoute>::from(&(String::new(), path.to_owned(), String::new()));
|
||||||
sycamore::render_to_string(|| view! { UI(route) })
|
sycamore::render_to_string(|| view! { UI(Some(route)) })
|
||||||
}
|
}
|
||||||
|
105
web/src/web.rs
105
web/src/web.rs
@ -22,7 +22,6 @@ use sycamore::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
fn route_switch<G: Html>(route: ReadSignal<AppRoutes>) -> View<G> {
|
fn route_switch<G: Html>(route: ReadSignal<AppRoutes>) -> View<G> {
|
||||||
// NOTE(jwall): This needs to not be a dynamic node. The rules around
|
// NOTE(jwall): This needs to not be a dynamic node. The rules around
|
||||||
@ -53,36 +52,6 @@ fn route_switch<G: Html>(route: ReadSignal<AppRoutes>) -> View<G> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
fn route_switch<G: Html>(route: ReadSignal<AppRoutes>) -> View<G> {
|
|
||||||
// NOTE(jwall): This needs to not be a dynamic node. The rules around
|
|
||||||
// this are somewhat unclear and underdocumented for Sycamore. But basically
|
|
||||||
// avoid conditionals in the `view!` macro calls here.
|
|
||||||
cloned!((route) => match route.get().as_ref() {
|
|
||||||
AppRoutes::Plan => view! {
|
|
||||||
PlanPage()
|
|
||||||
},
|
|
||||||
AppRoutes::Inventory => view! {
|
|
||||||
InventoryPage()
|
|
||||||
},
|
|
||||||
AppRoutes::Cook => view! {
|
|
||||||
CookPage()
|
|
||||||
},
|
|
||||||
AppRoutes::Recipe(idx) => view! {
|
|
||||||
RecipePage(RecipePageProps { recipe: Signal::new(idx.clone()) })
|
|
||||||
},
|
|
||||||
AppRoutes::NotFound => view! {
|
|
||||||
// TODO(Create a real one)
|
|
||||||
PlanPage()
|
|
||||||
},
|
|
||||||
AppRoutes::Error(ref e) => {
|
|
||||||
let e = e.clone();
|
|
||||||
view! {
|
|
||||||
"Error: " (e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn get_appservice() -> AppService<AsyncFileStore> {
|
fn get_appservice() -> AppService<AsyncFileStore> {
|
||||||
@ -93,29 +62,29 @@ fn get_appservice() -> AppService<HttpStore> {
|
|||||||
AppService::new(recipe_store::HttpStore::new("/api/v1".to_owned()))
|
AppService::new(recipe_store::HttpStore::new("/api/v1".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[component(RouterComponent<G>)]
|
#[component(RouterComponent<G>)]
|
||||||
fn rounter_component() -> View<G> {
|
fn router_component(route: Option<AppRoutes>) -> View<G> {
|
||||||
view! {
|
match route {
|
||||||
Router(RouterProps{
|
Some(route) => {
|
||||||
route: AppRoutes::default(),
|
view! {
|
||||||
browser_integration: BrowserIntegration::new(),
|
StaticRouter(StaticRouterProps{route: route, route_select: route_switch})
|
||||||
route_select: route_switch,
|
}
|
||||||
})
|
}
|
||||||
}
|
None => {
|
||||||
}
|
view! {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
Router(RouterProps{
|
||||||
#[component(RouterComponent<G>)]
|
route: AppRoutes::default(),
|
||||||
fn rounter_component(route: AppRoutes) -> View<G> {
|
browser_integration: BrowserIntegration::new(),
|
||||||
view! {
|
route_select: route_switch,
|
||||||
StaticRouter(StaticRouterProps{route: route, route_select: route_switch})
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
#[component(UI<G>)]
|
#[component(UI<G>)]
|
||||||
pub fn ui() -> View<G> {
|
pub fn ui(route: Option<AppRoutes>) -> View<G> {
|
||||||
let app_service = get_appservice();
|
let app_service = get_appservice();
|
||||||
info!("Starting UI");
|
info!("Starting UI");
|
||||||
view! {
|
view! {
|
||||||
@ -143,46 +112,6 @@ pub fn ui() -> View<G> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
div(class="app") {
|
|
||||||
Header()
|
|
||||||
RouterComponent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
#[instrument]
|
|
||||||
#[component(UI<G>)]
|
|
||||||
pub fn ui(route: AppRoutes) -> View<G> {
|
|
||||||
let app_service = get_appservice();
|
|
||||||
info!("Rendering UI");
|
|
||||||
view! {
|
|
||||||
// NOTE(jwall): Set the app_service in our toplevel scope. Children will be able
|
|
||||||
// to find the service as long as they are a child of this scope.
|
|
||||||
ContextProvider(ContextProviderProps {
|
|
||||||
value: app_service.clone(),
|
|
||||||
children: || {
|
|
||||||
create_effect(move || {
|
|
||||||
spawn_local_in_scope({
|
|
||||||
let mut app_service = app_service.clone();
|
|
||||||
async move {
|
|
||||||
debug!("fetching recipes");
|
|
||||||
match app_service.fetch_recipes_from_storage() {
|
|
||||||
Ok((_, Some(recipes))) => {
|
|
||||||
app_service.set_recipes(recipes);
|
|
||||||
}
|
|
||||||
Ok((_, None)) => {
|
|
||||||
error!("No recipes to find");
|
|
||||||
}
|
|
||||||
Err(msg) => error!("Failed to get recipes {}", msg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
view!{
|
|
||||||
div(class="app") {
|
div(class="app") {
|
||||||
Header()
|
Header()
|
||||||
RouterComponent(route)
|
RouterComponent(route)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user