Update leptos + add WIP translations
This commit is contained in:
parent
68ca7284fb
commit
14cff1b306
7 changed files with 352 additions and 585 deletions
617
Cargo.lock
generated
617
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -16,7 +16,7 @@ leptos_router = { version = "0.6", features = ["nightly"] }
|
|||
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
|
||||
tower = { version = "0.4", features = ["util"], optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
wasm-bindgen = "=0.2.95"
|
||||
wasm-bindgen = "=0.2.100"
|
||||
thiserror = "1"
|
||||
tracing = { version = "0.1", optional = true }
|
||||
http = "1"
|
||||
|
@ -50,8 +50,8 @@ ssr = [
|
|||
|
||||
[package.metadata.leptos-i18n]
|
||||
default = "en"
|
||||
# locales = ["en", "fr", "fi", "et", "sv", "eo", "jbo"]
|
||||
locales = ["en"]
|
||||
# locales = ["en", "fr", "fi", "sv", "eo", "uk", "et", "jbo"]
|
||||
locales = ["en", "fr", "fi"]
|
||||
|
||||
# Defines a size-optimized profile for the WASM bundle in release mode
|
||||
[profile.wasm-release]
|
||||
|
@ -81,7 +81,7 @@ style-file = "style/main.scss"
|
|||
assets-dir = "public"
|
||||
|
||||
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
|
||||
site-addr = "127.0.0.1:3000"
|
||||
site-addr = "0.0.0.0:3000"
|
||||
|
||||
# The port to use for automatic reload monitoring
|
||||
reload-port = 3001
|
||||
|
|
|
@ -6,7 +6,5 @@ blog: Blog
|
|||
welcome_blog: Welcome to my blog!
|
||||
|
||||
gallery: Gallery
|
||||
gallery_title: Gallery
|
||||
gallery_description: aaa
|
||||
|
||||
tanguy_gerome: Tanguy Gérôme
|
||||
|
|
10
src/app.rs
10
src/app.rs
|
@ -59,8 +59,8 @@ pub fn LanguageSwitcher() -> impl IntoView {
|
|||
<div class="language-switcher main-width">
|
||||
<p>{t!(i18n, available_in)}</p>
|
||||
<button class="link" on:click=move |_| i18n.set_locale(Locale::en)>english</button>
|
||||
// <button class="link" on:click=move |_| i18n.set_locale(Locale::fr)>français</button>
|
||||
// <button class="link" on:click=move |_| i18n.set_locale(Locale::fi)>suomi</button>
|
||||
<button class="link" on:click=move |_| i18n.set_locale(Locale::fr)>français</button>
|
||||
<button class="link" on:click=move |_| i18n.set_locale(Locale::fi)>suomi</button>
|
||||
// <button class="link" on:click=move |_| i18n.set_locale(Locale::et)>eesti</button>
|
||||
// <button class="link" on:click=move |_| i18n.set_locale(Locale::sv)>svenska</button>
|
||||
// <button class="link" on:click=move |_| i18n.set_locale(Locale::eo)>esperanto</button>
|
||||
|
@ -92,7 +92,7 @@ pub fn Header() -> impl IntoView {
|
|||
/>
|
||||
</div>
|
||||
|
||||
// <LanguageSwitcher/>
|
||||
<LanguageSwitcher/>
|
||||
</header>
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ pub fn HomePage() -> impl IntoView {
|
|||
<main class="main-width">
|
||||
<h1>Welcome!</h1>
|
||||
|
||||
<p>"I'm "<b>Tanguy Gérôme</b>, a 26 year old software developer, amateur photographer, and over all nerd living in Helsinki, Finland, originally from Cornimont, France.</p>
|
||||
<p>I am <b>Tanguy Gérôme</b>, a 26 year old software developer, amateur photographer, and over all nerd living in Helsinki, Finland, originally from Cornimont, France.</p>
|
||||
|
||||
<p>
|
||||
On here you can find my personal photography portfolio, and (coming) a blog where I scribble about whatever comes to mind in relation to my hobbies and interests, including:
|
||||
|
@ -137,6 +137,8 @@ pub fn HomePage() -> impl IntoView {
|
|||
</ul>
|
||||
</p>
|
||||
|
||||
<p>I am also using this website as a way to practice in my language learning journey, so expect unfinished and low quality translations for anything other than English and French :D</p>
|
||||
|
||||
<p>This website is still under construction, more content to come (hopefully) soon.</p>
|
||||
|
||||
// <Await future=move || get_rich_text_page("home-page".to_string()) let:page>
|
||||
|
|
44
src/blog.rs
44
src/blog.rs
|
@ -3,8 +3,8 @@ use leptos_router::*;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::i18n::*;
|
||||
use crate::services::contentful::get_rich_text_page;
|
||||
use crate::services::rich_text;
|
||||
// use crate::services::contentful::get_markdown_page;
|
||||
// use crate::services::rich_text;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct BlogPostMetadata {
|
||||
|
@ -75,29 +75,29 @@ pub fn BlogList() -> impl IntoView {
|
|||
|
||||
#[component]
|
||||
pub fn BlogPost() -> impl IntoView {
|
||||
let params = use_params::<BlogPostParams>();
|
||||
let slug= move || {
|
||||
params.with(|params| params.as_ref()
|
||||
.map(|params| params.slug.clone())
|
||||
.unwrap())
|
||||
};
|
||||
let blog_page = create_resource(|| (), move |_| async move { get_rich_text_page(slug()).await });
|
||||
// let params = use_params::<BlogPostParams>();
|
||||
// let slug= move || {
|
||||
// params.with(|params| params.as_ref()
|
||||
// .map(|params| params.slug.clone())
|
||||
// .unwrap())
|
||||
// };
|
||||
// let blog_page = create_resource(|| (), move |_| async move { get_rich_text_page(slug()).await });
|
||||
|
||||
view! {
|
||||
<main class="main-width">
|
||||
<Suspense fallback=move || view! { <div>"Loading..."</div> }>
|
||||
{match blog_page.get().unwrap_or(Err(ServerFnError::ServerError("Loading...".to_string()))) {
|
||||
Ok(page) => {
|
||||
view! {
|
||||
<div>
|
||||
<h1>{page.english.title}</h1>
|
||||
{rich_text::document_handler(&page.english.rich_text_content)}
|
||||
</div>
|
||||
}
|
||||
},
|
||||
Err(error) => view! { <div>"Error: "{error.to_string()}</div> }
|
||||
}}
|
||||
</Suspense>
|
||||
// <Suspense fallback=move || view! { <div>"Loading..."</div> }>
|
||||
// {match blog_page.get().unwrap_or(Err(ServerFnError::ServerError("Loading...".to_string()))) {
|
||||
// Ok(page) => {
|
||||
// view! {
|
||||
// <div>
|
||||
// <h1>{page.english.title}</h1>
|
||||
// {rich_text::document_handler(&page.english.rich_text_content)}
|
||||
// </div>
|
||||
// }
|
||||
// },
|
||||
// Err(error) => view! { <div>"Error: "{error.to_string()}</div> }
|
||||
// }}
|
||||
// </Suspense>
|
||||
</main>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,257 +1,40 @@
|
|||
use std::env;
|
||||
// use reqwest::StatusCode;
|
||||
use leptos::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
|
||||
// use crate::services::rich_text;
|
||||
|
||||
//pub struct Client {
|
||||
// access_token: String,
|
||||
// space_id: String,
|
||||
// base_url: String,
|
||||
// environment_id: String,
|
||||
//}
|
||||
|
||||
//impl Client {
|
||||
// pub fn new(
|
||||
// access_token: &str,
|
||||
// space_id: &str,
|
||||
// base_url: &str,
|
||||
// environment_id: &str,
|
||||
// ) -> Client {
|
||||
// Client {
|
||||
// base_url: base_url.into(),
|
||||
// access_token: access_token.into(),
|
||||
// space_id: space_id.into(),
|
||||
// environment_id: environment_id.into(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn get_entries_url(&self, query_string: &str) -> String {
|
||||
// format!(
|
||||
// "{base_url}/{space_id}/environments/{environment}/entries{query_string}",
|
||||
// base_url = &self.base_url,
|
||||
// space_id = &self.space_id,
|
||||
// environment = &self.environment_id,
|
||||
// query_string = &query_string
|
||||
// )
|
||||
// }
|
||||
|
||||
// pub async fn get_entries_by_query_string<T>(
|
||||
// &self,
|
||||
// query_string: &str
|
||||
// ) -> Result<Vec<T>, Box<dyn std::error::Error>>
|
||||
// where
|
||||
// for<'a> T: Serialize + Deserialize<'a>,
|
||||
// {
|
||||
// let url = self.get_entries_url(query_string);
|
||||
// let reqwest_client = reqwest::Client::new();
|
||||
// let request = reqwest_client.get(&url).bearer_auth(&self.access_token);
|
||||
// let response = request.send().await?;
|
||||
// let json_response = match response.status() {
|
||||
// StatusCode::OK => {
|
||||
// let json = response.json::<serde_json::Value>().await?;
|
||||
// Some(json)
|
||||
// },
|
||||
// StatusCode::NOT_FOUND => None,
|
||||
// _ => {
|
||||
// unimplemented!();
|
||||
// },
|
||||
// };
|
||||
// match json_response {
|
||||
// Some(json) => {
|
||||
// if let Some(items) = json.clone().get_mut("items") {
|
||||
// if items.is_array() {
|
||||
// if let Some(includes) = json.get("includes") {
|
||||
// self.resolve_array(items, includes)?;
|
||||
// } else {
|
||||
// let includes = serde_json::Value::default();
|
||||
// self.resolve_array(items, &includes)?;
|
||||
// }
|
||||
|
||||
// let ar_string = items.to_string();
|
||||
// let entries = serde_json::from_str::<Vec<T>>(ar_string.as_str())?;
|
||||
// Ok(entries)
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
// },
|
||||
// _ => unimplemented!(),
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn resolve_array(
|
||||
// &self,
|
||||
// value: &mut serde_json::Value,
|
||||
// includes: &serde_json::Value,
|
||||
// ) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// let items = value.as_array_mut().unwrap();
|
||||
// for item in items {
|
||||
// if item.is_object() {
|
||||
// self.resolve_object(item, includes)?;
|
||||
// } else if item.is_string() || item.is_number() {
|
||||
// // do nothing
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// fn resolve_object(
|
||||
// &self,
|
||||
// value: &mut serde_json::Value,
|
||||
// includes: &serde_json::Value,
|
||||
// ) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// if let Some(sys) = value.get("sys") {
|
||||
// if let Some(sys_type) = sys.get("type") {
|
||||
// if sys_type == "Entry" {
|
||||
// self.resolve_entry(value, includes)?;
|
||||
// } else if sys_type == "Link" {
|
||||
// self.resolve_link(value, includes)?;
|
||||
// } else {
|
||||
// let node_type = value["nodeType"].clone();
|
||||
// if node_type == "document" {
|
||||
// // log::warn!("TODO: Richtext is not yet implemented");
|
||||
// } else {
|
||||
// unimplemented!(
|
||||
// "{} - {} not implemented for {}",
|
||||
// &sys_type,
|
||||
// &node_type,
|
||||
// &value
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// unimplemented!("sys.type do not exist, though sys exists") // TODO: Can this ever happen?
|
||||
// }
|
||||
// } else {
|
||||
// // Do nothing, as it likely a json object
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// fn resolve_asset(&self, value: &mut serde_json::Value) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// if let Some(fields) = value.get_mut("fields") {
|
||||
// if fields.is_object() {
|
||||
// *value = fields.clone();
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// fn resolve_entry(
|
||||
// &self,
|
||||
// value: &mut serde_json::Value,
|
||||
// includes: &serde_json::Value,
|
||||
// ) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// if let Some(fields) = value.get_mut("fields") {
|
||||
// if fields.is_object() {
|
||||
// let entry_object = fields.as_object_mut().unwrap();
|
||||
// for (_field_name, field_value) in entry_object {
|
||||
// if field_value.is_object() {
|
||||
// self.resolve_object(field_value, includes)?;
|
||||
// } else if field_value.is_array() {
|
||||
// self.resolve_array(field_value, includes)?;
|
||||
// } else {
|
||||
// // Regular string, number, etc, values. No need to do anything.
|
||||
// }
|
||||
// }
|
||||
// *value = fields.clone();
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// fn resolve_link(
|
||||
// &self,
|
||||
// value: &mut serde_json::Value,
|
||||
// includes: &serde_json::Value,
|
||||
// ) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// let link_type = value["sys"]["linkType"].clone();
|
||||
// let link_id = value["sys"]["id"].clone();
|
||||
// if link_type == "Entry" {
|
||||
// let included_entries = includes["Entry"].as_array().unwrap();
|
||||
// let mut filtered_entries = included_entries
|
||||
// .iter()
|
||||
// .filter(|entry| entry["sys"]["id"] == link_id)
|
||||
// .take(1);
|
||||
// let linked_entry = filtered_entries.next();
|
||||
// if let Some(entry) = linked_entry {
|
||||
// let mut entry = entry.clone();
|
||||
// self.resolve_entry(&mut entry, includes)?;
|
||||
// *value = entry;
|
||||
// //value["fields"] = entry["fields"].clone();
|
||||
// //*value = entry["fields"].clone();
|
||||
// }
|
||||
// } else if link_type == "Asset" {
|
||||
// let included_assets = includes["Asset"].as_array().unwrap();
|
||||
// let mut filtered_assets = included_assets
|
||||
// .iter()
|
||||
// .filter(|entry| entry["sys"]["id"] == link_id)
|
||||
// .take(1);
|
||||
// let linked_asset = filtered_assets.next();
|
||||
// if let Some(asset) = linked_asset {
|
||||
// let mut asset = asset.clone();
|
||||
// self.resolve_asset(&mut asset)?;
|
||||
// *value = asset;
|
||||
// }
|
||||
// } else {
|
||||
// unimplemented!();
|
||||
// }
|
||||
|
||||
// //*value = value["fields"].clone();
|
||||
// Ok(())
|
||||
// }
|
||||
//}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RichTextPage {
|
||||
pub struct MarkdownPage {
|
||||
pub title: String,
|
||||
pub page_slug: String,
|
||||
// pub rich_text_content: rich_text::RichTextNode,
|
||||
pub rich_text_content: serde_json::Value,
|
||||
pub slug: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RichTextPageLanguagesWrapper {
|
||||
pub struct MarkdownPageLanguagesWrapper {
|
||||
pub internal_title: String,
|
||||
pub english: RichTextPage,
|
||||
pub slug: String,
|
||||
pub english: MarkdownPage,
|
||||
}
|
||||
|
||||
#[server(GetRichTextPage, "/api", "GetJson")]
|
||||
pub async fn get_rich_text_page(slug: String) -> Result<RichTextPageLanguagesWrapper, ServerFnError> {
|
||||
pub async fn get_markdown_page(slug: String) -> Result<MarkdownPageLanguagesWrapper, ServerFnError> {
|
||||
let contentful_client = get_contentful_client();
|
||||
// let builder = contentful::QueryBuilder::new()
|
||||
// .content_type_is("richTextPageLanguagesWrapper")
|
||||
// .include(10)
|
||||
// .field_equals("fields.slug", &slug);
|
||||
let query_string = format!("?content_type=richTextPageLanguagesWrapper&include=10&fields.slug={}", slug);
|
||||
let pages = contentful_client.get_entries_by_query_string::<RichTextPageLanguagesWrapper>(&query_string).await;
|
||||
let builder = contentful::QueryBuilder::new()
|
||||
.content_type_is("markdownPageLanguagesWrapper")
|
||||
.include(10)
|
||||
.field_equals("fields.slug", &slug);
|
||||
// let query_string = format!("?content_type=markdownPageLanguagesWrapper&include=10&fields.slug={}", slug);
|
||||
// let pages = contentful_client.get_entries_by_query_string::<RichTextPageLanguagesWrapper>(&query_string).await;
|
||||
let pages = contentful_client.get_entries::<MarkdownPageLanguagesWrapper>(Some(builder)).await;
|
||||
match pages {
|
||||
Ok(found_pages) => {
|
||||
if found_pages.len() != 1 {
|
||||
return Err(ServerFnError::ServerError("Found none or more than one".to_string()));
|
||||
}
|
||||
let english_rich_text_content = found_pages[0].english.rich_text_content.clone();
|
||||
dbg!(english_rich_text_content);
|
||||
let english_content = found_pages[0].english.content.clone();
|
||||
dbg!(english_content);
|
||||
Ok(found_pages[0].clone())
|
||||
},
|
||||
Err(e) => Err(ServerFnError::ServerError(e.to_string())),
|
||||
|
|
|
@ -87,7 +87,7 @@ body {
|
|||
.text {
|
||||
@include top-level-padding;
|
||||
flex-basis: auto;
|
||||
flex-shrink: 0;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
|
||||
display: flex;
|
||||
|
@ -103,14 +103,17 @@ body {
|
|||
}
|
||||
|
||||
.links {
|
||||
flex-shrink: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
text-align: right;
|
||||
gap: 8px;
|
||||
|
||||
a {
|
||||
color: white!important;
|
||||
font-size: 22px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue