build: migrate to Dioxus 0.6 (#61)
This commit is contained in:
		| @@ -1,7 +1,6 @@ | |||||||
| /.dioxus/ | /.dioxus/ | ||||||
| /.git/ | /.git/ | ||||||
| /.github/ | /.github/ | ||||||
| /dist/ |  | ||||||
| /debug/ | /debug/ | ||||||
| /node_modules/ | /node_modules/ | ||||||
| /static/ | /static/ | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.idea/dataSources.local.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/dataSources.local.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="dataSourceStorageLocal" created-in="RR-242.21829.114"> |   <component name="dataSourceStorageLocal" created-in="RR-243.21565.245"> | ||||||
|     <data-source name="todo_baggins@localhost" uuid="1658668c-c2b8-426d-a22f-16fbad9eff0b"> |     <data-source name="todo_baggins@localhost" uuid="1658668c-c2b8-426d-a22f-16fbad9eff0b"> | ||||||
|       <database-info product="PostgreSQL" version="16.4 (Debian 16.4-1.pgdg120+1)" jdbc-version="4.2" driver-name="PostgreSQL JDBC Driver" driver-version="42.6.0" dbms="POSTGRES" exact-version="16.4" exact-driver-version="42.6"> |       <database-info product="PostgreSQL" version="16.4 (Debian 16.4-1.pgdg120+1)" jdbc-version="4.2" driver-name="PostgreSQL JDBC Driver" driver-version="42.6.0" dbms="POSTGRES" exact-version="16.4" exact-driver-version="42.6"> | ||||||
|         <identifier-quote-string>"</identifier-quote-string> |         <identifier-quote-string>"</identifier-quote-string> | ||||||
|   | |||||||
							
								
								
									
										3818
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3818
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										49
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -7,30 +7,39 @@ edition = "2021" | |||||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
|  | dioxus = { version = "0.6.0", features = ["fullstack", "router"] } | ||||||
|  | dioxus-query = "0.6.0" | ||||||
|  | dioxus-i18n = "0.3.0" | ||||||
|  |  | ||||||
|  | async-std = "1.12.0" | ||||||
| chrono = { version = "0.4.38", features = ["serde", "unstable-locales"] } | chrono = { version = "0.4.38", features = ["serde", "unstable-locales"] } | ||||||
| diesel = { version = "2.2.2", features = ["chrono", "postgres", "postgres_backend", "serde_json"] } | diesel = { version = "2.2.2", features = ["chrono", "postgres", "postgres_backend", "serde_json"] } | ||||||
|  |  | ||||||
| dioxus = { version = "0.5", features = ["fullstack", "router"] } |  | ||||||
|  |  | ||||||
| # Debug |  | ||||||
| dioxus-logger = "0.5.1" |  | ||||||
| dotenvy = "0.15.7" |  | ||||||
| serde = "1.0.208" |  | ||||||
| validator = { version = "0.18.1", features = ["derive"] } |  | ||||||
| serde_json = "1.0.125" |  | ||||||
| tracing = "0.1.40" |  | ||||||
| tracing-wasm = "0.2.1" |  | ||||||
| serde_with = { version = "3.9.0", features = ["chrono_0_4"] } |  | ||||||
| async-std = "1.12.0" |  | ||||||
| dioxus-query = "0.5.1" |  | ||||||
| time = "0.3.36" |  | ||||||
| dioxus-sdk = { version = "0.5.0", features = ["i18n"] } |  | ||||||
| unic-langid-impl = "0.9.5" |  | ||||||
| voca_rs = "1.15.2" |  | ||||||
| diesel_migrations = { version = "2.2.0", features = ["postgres"] } | diesel_migrations = { version = "2.2.0", features = ["postgres"] } | ||||||
|  | dotenvy = "0.15.7" | ||||||
| feruca = "0.10.0" | feruca = "0.10.0" | ||||||
|  | serde = "1.0.208" | ||||||
|  | serde_json = "1.0.125" | ||||||
|  | serde_with = { version = "3.9.0", features = ["chrono_0_4"] } | ||||||
|  | time = "0.3.36" | ||||||
|  | tracing = "0.1.40" | ||||||
|  | unic-langid-impl = { version = "0.9.5", features = ["serde"] } | ||||||
|  | validator = { version = "0.19.0", features = ["derive"] } | ||||||
|  | voca_rs = "1.15.2" | ||||||
|  |  | ||||||
| [features] | [features] | ||||||
| default = [] | default = ["web"] | ||||||
| server = ["dioxus/axum"] | desktop = ["dioxus/desktop"] | ||||||
|  | mobile = ["dioxus/mobile"] | ||||||
| web = ["dioxus/web"] | web = ["dioxus/web"] | ||||||
|  |  | ||||||
|  | [profile] | ||||||
|  |  | ||||||
|  | [profile.wasm-dev] | ||||||
|  | inherits = "dev" | ||||||
|  | opt-level = 1 | ||||||
|  |  | ||||||
|  | [profile.server-dev] | ||||||
|  | inherits = "dev" | ||||||
|  |  | ||||||
|  | [profile.android-dev] | ||||||
|  | inherits = "dev" | ||||||
|   | |||||||
| @@ -30,13 +30,7 @@ watch_path = ["src", "assets"] | |||||||
| [web.resource] | [web.resource] | ||||||
|  |  | ||||||
| # CSS style file | # CSS style file | ||||||
|  | style = [] | ||||||
| style = [ |  | ||||||
|     "/styles/tailwind_output.css", |  | ||||||
|     "/styles/fonts.css", |  | ||||||
|     "/styles/input_number_arrows.css", |  | ||||||
|     "/styles/input_range.css" |  | ||||||
| ] |  | ||||||
|  |  | ||||||
| # Javascript code file | # Javascript code file | ||||||
| script = ["https://kit.fontawesome.com/3c1b409f8f.js"] | script = ["https://kit.fontawesome.com/3c1b409f8f.js"] | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|         font-style: normal; |         font-style: normal; | ||||||
|         font-weight: 100 900; |         font-weight: 100 900; | ||||||
|         font-display: swap; |         font-display: swap; | ||||||
|         src: url("/fonts/inter_variable.woff2") format("woff2"); |         src: url("/assets/fonts/inter_variable.woff2") format("woff2"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @font-face { |     @font-face { | ||||||
| @@ -12,6 +12,6 @@ | |||||||
|         font-style: italic; |         font-style: italic; | ||||||
|         font-weight: 100 900; |         font-weight: 100 900; | ||||||
|         font-display: swap; |         font-display: swap; | ||||||
|         src: url("/fonts/inter_variable_italic.woff2") format("woff2"); |         src: url("/assets/fonts/inter_variable_italic.woff2") format("woff2"); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ services: | |||||||
|       - ./Cargo.toml:/srv/app/Cargo.toml |       - ./Cargo.toml:/srv/app/Cargo.toml | ||||||
|       - ./diesel.toml:/srv/app/diesel.toml |       - ./diesel.toml:/srv/app/diesel.toml | ||||||
|       - ./Dioxus.toml:/srv/app/Dioxus.toml |       - ./Dioxus.toml:/srv/app/Dioxus.toml | ||||||
|       - ./index.html:/srv/app/index.html |  | ||||||
|       - ./package.json:/srv/app/package.json |       - ./package.json:/srv/app/package.json | ||||||
|       - ./package-lock.json:/srv/app/package-lock.json |       - ./package-lock.json:/srv/app/package-lock.json | ||||||
|     restart: always |     restart: always | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| FROM rust:1.80-bookworm | FROM rust:1.83-bookworm | ||||||
|  |  | ||||||
| RUN rustup target add wasm32-unknown-unknown && \ | RUN rustup target add wasm32-unknown-unknown && \ | ||||||
|     cargo install dioxus-cli diesel_cli && \ |     cargo install dioxus-cli diesel_cli && \ | ||||||
| @@ -16,7 +16,7 @@ RUN chown -R 1000:1000 /srv/app && \ | |||||||
|     mkdir -p /.local/share/dioxus && \ |     mkdir -p /.local/share/dioxus && \ | ||||||
|     chown -R 1000:1000 /.local/share/dioxus |     chown -R 1000:1000 /.local/share/dioxus | ||||||
|  |  | ||||||
| HEALTHCHECK CMD curl --fail http://localhost:8000 || exit 1 | HEALTHCHECK CMD curl --fail -H "Accept: text/html" http://localhost:8000 || exit 1 | ||||||
|  |  | ||||||
| USER 1000:1000 | USER 1000:1000 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ stdout_logfile_maxbytes=0 | |||||||
| redirect_stderr=true | redirect_stderr=true | ||||||
|  |  | ||||||
| [program:dx] | [program:dx] | ||||||
| command=dx serve | command=dx serve --addr 0.0.0.0 --port 8000 | ||||||
| directory=/srv/app | directory=/srv/app | ||||||
| autostart=true | autostart=true | ||||||
| autorestart=true | autorestart=true | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| FROM rust:1.80-bookworm AS builder | FROM rust:1.83-bookworm AS builder | ||||||
|  |  | ||||||
| RUN rustup target add wasm32-unknown-unknown && \ | RUN rustup target add wasm32-unknown-unknown && \ | ||||||
|     cargo install dioxus-cli diesel_cli && \ |     cargo install dioxus-cli diesel_cli && \ | ||||||
| @@ -15,15 +15,17 @@ FROM debian:bookworm-slim AS runner | |||||||
|  |  | ||||||
| RUN apt-get update && apt-get install -y libpq5=15.8-0+deb12u1 | RUN apt-get update && apt-get install -y libpq5=15.8-0+deb12u1 | ||||||
|  |  | ||||||
| COPY --from=builder /srv/app/dist /srv/app/dist | COPY --from=builder /srv/app/target/dx/todo-baggins/release/web /srv/app | ||||||
| COPY .env /srv/app/.env | COPY .env /srv/app/.env | ||||||
|  |  | ||||||
| RUN chown -R 1000:1000 /srv/app | RUN chown -R 1000:1000 /srv/app | ||||||
|  |  | ||||||
| WORKDIR /srv/app | WORKDIR /srv/app | ||||||
|  |  | ||||||
| HEALTHCHECK CMD curl --fail http://localhost:8000 || exit 1 | HEALTHCHECK CMD curl --fail -H "Accept: text/html" http://localhost || exit 1 | ||||||
|  |  | ||||||
| USER 1000:1000 | USER 1000:1000 | ||||||
|  |  | ||||||
| CMD ["./dist/todo-baggins"] | ENV IP="0.0.0.0" | ||||||
|  | ENV PORT="80" | ||||||
|  | CMD ["./server"] | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								index.html
									
									
									
									
									
								
							| @@ -1,24 +0,0 @@ | |||||||
| <!DOCTYPE html> |  | ||||||
| <html class="min-h-screen"> |  | ||||||
| <head> |  | ||||||
|     <title>{app_title}</title> |  | ||||||
|     <link rel="manifest" href="manifest.json"> |  | ||||||
|     <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/> |  | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> |  | ||||||
|     <meta charset="UTF-8"/> |  | ||||||
|     {style_include} |  | ||||||
| </head> |  | ||||||
| <body class="min-h-screen"> |  | ||||||
| <div id="main" class="min-h-screen"></div> |  | ||||||
| <script type="module"> |  | ||||||
|     import init from "/{base_path}/assets/dioxus/{app_name}.js"; |  | ||||||
|  |  | ||||||
|     init("/{base_path}/assets/dioxus/{app_name}_bg.wasm").then(wasm => { |  | ||||||
|         if (wasm.__wbindgen_start == undefined) { |  | ||||||
|             wasm.main(); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| </script> |  | ||||||
| {script_include} |  | ||||||
| </body> |  | ||||||
| </html> |  | ||||||
| @@ -1,21 +1,45 @@ | |||||||
|  | use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||||
| use crate::route::Route; | use crate::route::Route; | ||||||
|  | use crate::server::internationalization::get_language_identifier; | ||||||
| use dioxus::core_macro::rsx; | use dioxus::core_macro::rsx; | ||||||
| use dioxus::dioxus_core::Element; | use dioxus::dioxus_core::Element; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
| use dioxus_query::prelude::{use_init_query_client}; | use dioxus_i18n::prelude::*; | ||||||
| use crate::query::{QueryErrors, QueryKey, QueryValue}; | use dioxus_i18n::unic_langid::langid; | ||||||
| use dioxus_sdk::i18n::{use_init_i18n}; | use dioxus_query::prelude::use_init_query_client; | ||||||
| use crate::internationalization::get_languages; |  | ||||||
| use crate::server::internationalization::get_language_identifier; | const FAVICON: Asset = asset!("/assets/favicon.ico"); | ||||||
|  | const TAILWIND_CSS: Asset = asset!("/assets/styles/tailwind_output.css"); | ||||||
|  | const FONTS_CSS: Asset = asset!("/assets/styles/fonts.css"); | ||||||
|  | const INPUT_NUMBER_ARROWS_CSS: Asset = asset!("/assets/styles/input_number_arrows.css"); | ||||||
|  | const INPUT_RANGE_CSS: Asset = asset!("/assets/styles/input_range.css"); | ||||||
|  |  | ||||||
| #[component] | #[component] | ||||||
| pub(crate) fn App() -> Element { | pub(crate) fn App() -> Element { | ||||||
|     use_init_query_client::<QueryValue, QueryErrors, QueryKey>(); |     use_init_query_client::<QueryValue, QueryErrors, QueryKey>(); | ||||||
|      |  | ||||||
|     let language_identifier = use_server_future(get_language_identifier)?.unwrap().unwrap(); |     let language_identifier = use_server_future(get_language_identifier)? | ||||||
|     use_init_i18n(language_identifier.clone(), language_identifier, get_languages); |         .unwrap() | ||||||
|      |         .unwrap(); | ||||||
|  |     use_init_i18n(|| { | ||||||
|  |         I18nConfig::new(language_identifier) | ||||||
|  |             .with_locale(Locale::new_static( | ||||||
|  |                 langid!("cs-CZ"), | ||||||
|  |                 include_str!("../internationalization/cs_cz.ftl"), | ||||||
|  |             )) | ||||||
|  |             .with_locale(Locale::new_static( | ||||||
|  |                 langid!("en-US"), | ||||||
|  |                 include_str!("../internationalization/en_us.ftl"), | ||||||
|  |             )) | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     rsx! { |     rsx! { | ||||||
|  |         document::Link { rel: "icon", href: FAVICON } | ||||||
|  |         document::Link { rel: "stylesheet", href: TAILWIND_CSS } | ||||||
|  |         document::Link { rel: "stylesheet", href: FONTS_CSS } | ||||||
|  |         document::Link { rel: "stylesheet", href: INPUT_NUMBER_ARROWS_CSS } | ||||||
|  |         document::Link { rel: "stylesheet", href: INPUT_RANGE_CSS } | ||||||
|  |  | ||||||
|         div { |         div { | ||||||
|             class: "min-h-screen text-zinc-200 bg-zinc-800 pt-4 pb-36", |             class: "min-h-screen text-zinc-200 bg-zinc-800 pt-4 pb-36", | ||||||
|             Router::<Route> {} |             Router::<Route> {} | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ pub(crate) fn Navigation(expanded: Signal<bool>) -> Element { | |||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } else { None }} |             } else { VNode::empty() }} | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,9 +8,9 @@ use chrono::{Datelike, Local}; | |||||||
| use dioxus::core_macro::rsx; | use dioxus::core_macro::rsx; | ||||||
| use dioxus::dioxus_core::Element; | use dioxus::dioxus_core::Element; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
|  | use dioxus_i18n::prelude::i18n; | ||||||
|  | use dioxus_i18n::t; | ||||||
| use dioxus_query::prelude::QueryResult; | use dioxus_query::prelude::QueryResult; | ||||||
| use dioxus_sdk::i18n::use_i18; |  | ||||||
| use dioxus_sdk::translate; |  | ||||||
|  |  | ||||||
| const CALENDAR_LENGTH_DAYS: usize = 366 * 3; | const CALENDAR_LENGTH_DAYS: usize = 366 * 3; | ||||||
|  |  | ||||||
| @@ -23,14 +23,12 @@ pub(crate) fn CategoryCalendarPage() -> Element { | |||||||
|     }); |     }); | ||||||
|     let tasks_query_result = tasks.result(); |     let tasks_query_result = tasks.result(); | ||||||
|  |  | ||||||
|     let i18 = use_i18(); |  | ||||||
|  |  | ||||||
|     rsx! { |     rsx! { | ||||||
|         match tasks_query_result.value() { |         match tasks_query_result.value() { | ||||||
|             QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) |             QueryResult::Ok(QueryValue::TasksWithSubtasks(tasks)) | ||||||
|             | QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => { |             | QueryResult::Loading(Some(QueryValue::TasksWithSubtasks(tasks))) => { | ||||||
|                 let today_date = Local::now().date_naive(); |                 let today_date = Local::now().date_naive(); | ||||||
|                  |  | ||||||
|                 rsx! { |                 rsx! { | ||||||
|                     div { |                     div { | ||||||
|                         class: "pt-4 flex flex-col gap-8", |                         class: "pt-4 flex flex-col gap-8", | ||||||
| @@ -42,16 +40,15 @@ pub(crate) fn CategoryCalendarPage() -> Element { | |||||||
|                                     div { |                                     div { | ||||||
|                                         class: "pt-1", |                                         class: "pt-1", | ||||||
|                                         { |                                         { | ||||||
|                                             date_current.format_localized(translate!( |                                             date_current.format_localized(t!( | ||||||
|                                                     i18, |  | ||||||
|                                                     if date_current.year() == Local::now().year() { |                                                     if date_current.year() == Local::now().year() { | ||||||
|                                                         "formats.date_weekday_format" |                                                         "date-weekday-format" | ||||||
|                                                     } else { |                                                     } else { | ||||||
|                                                         "formats.date_weekday_year_format" |                                                         "date-weekday-year-format" | ||||||
|                                                     } |                                                     } | ||||||
|                                                 ).as_str(), |                                                 ).as_str(), | ||||||
|                                                 LocaleFromLanguageIdentifier::from( |                                                 LocaleFromLanguageIdentifier::from( | ||||||
|                                                     &(i18.selected_language)() |                                                     &i18n().language() | ||||||
|                                                 ).into() |                                                 ).into() | ||||||
|                                             ) |                                             ) | ||||||
|                                             .to_string() |                                             .to_string() | ||||||
| @@ -60,7 +57,7 @@ pub(crate) fn CategoryCalendarPage() -> Element { | |||||||
|                                 } |                                 } | ||||||
|                                 TaskList { |                                 TaskList { | ||||||
|                                     tasks: tasks.iter().filter(|task| { |                                     tasks: tasks.iter().filter(|task| { | ||||||
|                                         if let Category::Calendar { date, .. }  |                                         if let Category::Calendar { date, .. } | ||||||
|                                             = task.task().category() { |                                             = task.task().category() { | ||||||
|                                             *date == date_current |                                             *date == date_current | ||||||
|                                         } else { |                                         } else { | ||||||
| @@ -70,7 +67,7 @@ pub(crate) fn CategoryCalendarPage() -> Element { | |||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }    |                     } | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             QueryResult::Loading(None) => rsx! { |             QueryResult::Loading(None) => rsx! { | ||||||
|   | |||||||
| @@ -7,9 +7,9 @@ use crate::query::tasks::use_tasks_with_subtasks_in_category_query; | |||||||
| use crate::query::QueryValue; | use crate::query::QueryValue; | ||||||
| use chrono::Local; | use chrono::Local; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
|  | use dioxus_i18n::t; | ||||||
|  | use dioxus_i18n::use_i18n::i18n; | ||||||
| use dioxus_query::prelude::QueryResult; | use dioxus_query::prelude::QueryResult; | ||||||
| use dioxus_sdk::i18n::use_i18; |  | ||||||
| use dioxus_sdk::translate; |  | ||||||
| use voca_rs::Voca; | use voca_rs::Voca; | ||||||
|  |  | ||||||
| #[component] | #[component] | ||||||
| @@ -25,9 +25,7 @@ pub(crate) fn CategoryTodayPage() -> Element { | |||||||
|  |  | ||||||
|     let long_term_tasks_query = use_tasks_with_subtasks_in_category_query(Category::LongTerm); |     let long_term_tasks_query = use_tasks_with_subtasks_in_category_query(Category::LongTerm); | ||||||
|     let long_term_tasks_query_result = long_term_tasks_query.result(); |     let long_term_tasks_query_result = long_term_tasks_query.result(); | ||||||
|  |      | ||||||
|     let i18 = use_i18(); |  | ||||||
|  |  | ||||||
|     rsx! { |     rsx! { | ||||||
|         div { |         div { | ||||||
|             class: "pt-4 flex flex-col gap-8", |             class: "pt-4 flex flex-col gap-8", | ||||||
| @@ -46,7 +44,7 @@ pub(crate) fn CategoryTodayPage() -> Element { | |||||||
|                                 } |                                 } | ||||||
|                                 div { |                                 div { | ||||||
|                                     class: "mt-1", |                                     class: "mt-1", | ||||||
|                                     {translate!(i18, "long_term")._upper_first()} |                                     {t!("long-term")._upper_first()} | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                             div { |                             div { | ||||||
| @@ -97,7 +95,7 @@ pub(crate) fn CategoryTodayPage() -> Element { | |||||||
|                             panic!("Unexpected category."); |                             panic!("Unexpected category."); | ||||||
|                         } |                         } | ||||||
|                     }).cloned().collect::<Vec<TaskWithSubtasks>>(); |                     }).cloned().collect::<Vec<TaskWithSubtasks>>(); | ||||||
|          |  | ||||||
|                     rsx! { |                     rsx! { | ||||||
|                         if !overdue_tasks.is_empty() { |                         if !overdue_tasks.is_empty() { | ||||||
|                             div { |                             div { | ||||||
| @@ -109,7 +107,7 @@ pub(crate) fn CategoryTodayPage() -> Element { | |||||||
|                                     } |                                     } | ||||||
|                                     div { |                                     div { | ||||||
|                                         class: "mt-1", |                                         class: "mt-1", | ||||||
|                                         {translate!(i18, "overdue")._upper_first()} |                                         {t!("overdue")._upper_first()} | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
|                                 TaskList { |                                 TaskList { | ||||||
| @@ -128,18 +126,17 @@ pub(crate) fn CategoryTodayPage() -> Element { | |||||||
|                                 div { |                                 div { | ||||||
|                                     class: "mt-1", |                                     class: "mt-1", | ||||||
|                                     { |                                     { | ||||||
|                                         let format = translate!(i18, "formats.date_weekday_format"); |                                         let format = t!("date-weekday-format"); | ||||||
|                                         let today_date = today_date.format_localized( |                                         let today_date = today_date.format_localized( | ||||||
|                                             format.as_str(), |                                             format.as_str(), | ||||||
|                                             LocaleFromLanguageIdentifier::from( |                                             LocaleFromLanguageIdentifier::from( | ||||||
|                                                 &(i18.selected_language)() |                                                 &i18n().language() | ||||||
|                                             ).into() |                                             ).into() | ||||||
|                                         ).to_string(); |                                         ).to_string(); | ||||||
|                                         format!( |                                         format!( | ||||||
|                                             "{} – {}", |                                             "{} – {}", | ||||||
|                                             translate!(i18, "today")._upper_first(), |                                             t!("today")._upper_first(), | ||||||
|                                             if translate!(i18, "formats.weekday_lowercase_first") |                                             if t!("weekday-lowercase-first").parse().unwrap() { | ||||||
|                                                 .parse().unwrap() { |  | ||||||
|                                                 today_date._lower_first() |                                                 today_date._lower_first() | ||||||
|                                             } else { |                                             } else { | ||||||
|                                                 today_date |                                                 today_date | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ pub(crate) fn SubtasksForm(task: Task) -> Element { | |||||||
|                                     onchange: { |                                     onchange: { | ||||||
|                                         let subtask = subtask.clone(); |                                         let subtask = subtask.clone(); | ||||||
|                                         let task = task.clone(); |                                         let task = task.clone(); | ||||||
|                                         move |event| { |                                         move |event: Event<FormData>| { | ||||||
|                                             let subtask = subtask.clone(); |                                             let subtask = subtask.clone(); | ||||||
|                                             let task = task.clone(); |                                             let task = task.clone(); | ||||||
|                                             async move { |                                             async move { | ||||||
|   | |||||||
| @@ -11,9 +11,8 @@ use chrono::Duration; | |||||||
| use dioxus::core_macro::{component, rsx}; | use dioxus::core_macro::{component, rsx}; | ||||||
| use dioxus::dioxus_core::Element; | use dioxus::dioxus_core::Element; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
|  | use dioxus_i18n::t; | ||||||
| use dioxus_query::prelude::{use_query_client, QueryResult}; | use dioxus_query::prelude::{use_query_client, QueryResult}; | ||||||
| use dioxus_sdk::i18n::use_i18; |  | ||||||
| use dioxus_sdk::translate; |  | ||||||
| use crate::query::projects::use_projects_query; | use crate::query::projects::use_projects_query; | ||||||
|  |  | ||||||
| const REMINDER_OFFSETS: [Option<Duration>; 17] = [ | const REMINDER_OFFSETS: [Option<Duration>; 17] = [ | ||||||
| @@ -81,8 +80,6 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | |||||||
|     let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>(); |     let query_client = use_query_client::<QueryValue, QueryErrors, QueryKey>(); | ||||||
|     let task_for_submit = task.clone(); |     let task_for_submit = task.clone(); | ||||||
|  |  | ||||||
|     let i18 = use_i18(); |  | ||||||
|  |  | ||||||
|     rsx! { |     rsx! { | ||||||
|         div { |         div { | ||||||
|             class: "p-4 flex flex-col gap-4", |             class: "p-4 flex flex-col gap-4", | ||||||
| @@ -176,7 +173,7 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | |||||||
|                         id: "input_project", |                         id: "input_project", | ||||||
|                         option { |                         option { | ||||||
|                             value: 0, |                             value: 0, | ||||||
|                             {translate!(i18, "none")} |                             {t!("none")} | ||||||
|                         }, |                         }, | ||||||
|                         match projects_query.result().value() { |                         match projects_query.result().value() { | ||||||
|                             QueryResult::Ok(QueryValue::Projects(projects)) |                             QueryResult::Ok(QueryValue::Projects(projects)) | ||||||
| @@ -359,12 +356,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | |||||||
|                                             } else { |                                             } else { | ||||||
|                                                 format!("{} h", offset.num_hours()) |                                                 format!("{} h", offset.num_hours()) | ||||||
|                                             } |                                             } | ||||||
|                                         ).unwrap_or_else(|| translate!(i18, "none"))} |                                         ).unwrap_or_else(|| t!("none"))} | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                     _ => None |                     _ => VNode::empty() | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             if let Some(task) = task.as_ref() { |             if let Some(task) = task.as_ref() { | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ use dioxus::core_macro::rsx; | |||||||
| use dioxus::dioxus_core::Element; | use dioxus::dioxus_core::Element; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
| use dioxus_query::prelude::use_query_client; | use dioxus_query::prelude::use_query_client; | ||||||
|  | use tracing::info; | ||||||
| use crate::components::task_list_item::TaskListItem; | use crate::components::task_list_item::TaskListItem; | ||||||
| use crate::query::{QueryErrors, QueryKey, QueryValue}; | use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||||
| use crate::server::tasks::complete_task; | use crate::server::tasks::complete_task; | ||||||
| @@ -22,17 +23,17 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str> | |||||||
|                 div { |                 div { | ||||||
|                     key: "{task.task().id()}", |                     key: "{task.task().id()}", | ||||||
|                     class: format!( |                     class: format!( | ||||||
|                         "px-8 pt-5 {} flex flex-row gap-4 select-none {}", |                         "px-8 pt-4 {} flex flex-row gap-4 select-none {}", | ||||||
|                         if task.task().deadline().is_some() || !task.subtasks().is_empty() { |                         if task.task().deadline().is_some() || !task.subtasks().is_empty() { | ||||||
|                             "pb-0.5" |                             "pb-0.5" | ||||||
|                         } else if let Category::Calendar { time, .. } = task.task().category() { |                         } else if let Category::Calendar { time, .. } = task.task().category() { | ||||||
|                             if time.is_some() { |                             if time.is_some() { | ||||||
|                                 "pb-0.5" |                                 "pb-0.5" | ||||||
|                             } else { |                             } else { | ||||||
|                                 "pb-5" |                                 "pb-4" | ||||||
|                             } |                             } | ||||||
|                         } else { |                         } else { | ||||||
|                             "pb-5" |                             "pb-4" | ||||||
|                         }, |                         }, | ||||||
|                         if task_being_edited().is_some_and(|t| t.id() == task.task().id()) { |                         if task_being_edited().is_some_and(|t| t.id() == task.task().id()) { | ||||||
|                             "bg-zinc-700" |                             "bg-zinc-700" | ||||||
| @@ -44,7 +45,7 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str> | |||||||
|                     }, |                     }, | ||||||
|                     i { |                     i { | ||||||
|                         class: format!( |                         class: format!( | ||||||
|                             "{} text-3xl text-zinc-500", |                             "{} text-3xl align-middle h-9 text-zinc-500", | ||||||
|                             if *(task.task().category()) == Category::Done { |                             if *(task.task().category()) == Category::Done { | ||||||
|                                 "fa solid fa-square-check" |                                 "fa solid fa-square-check" | ||||||
|                             } else { |                             } else { | ||||||
| @@ -53,12 +54,13 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str> | |||||||
|                         ), |                         ), | ||||||
|                         onclick: { |                         onclick: { | ||||||
|                             let task = task.clone(); |                             let task = task.clone(); | ||||||
|                             move |event| { |                             move |event: Event<MouseData>| { | ||||||
|                                 // To prevent editing the task. |                                 // To prevent editing the task. | ||||||
|                                 event.stop_propagation(); |                                 event.stop_propagation(); | ||||||
|                                 let task = task.clone(); |                                 let task = task.clone(); | ||||||
|                                 async move { |                                 async move { | ||||||
|                                     let completed_task = complete_task(task.task().id()).await.unwrap(); |                                     let completed_task = complete_task(task.task().id()).await | ||||||
|  |                                         .unwrap(); | ||||||
|                                     let mut query_keys = vec![ |                                     let mut query_keys = vec![ | ||||||
|                                         QueryKey::Tasks, |                                         QueryKey::Tasks, | ||||||
|                                         QueryKey::TasksInCategory( |                                         QueryKey::TasksInCategory( | ||||||
|   | |||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | use dioxus_i18n::prelude::i18n; | ||||||
| use crate::internationalization::LocaleFromLanguageIdentifier; | use crate::internationalization::LocaleFromLanguageIdentifier; | ||||||
| use crate::models::category::Category; | use crate::models::category::Category; | ||||||
| use crate::models::task::TaskWithSubtasks; | use crate::models::task::TaskWithSubtasks; | ||||||
| @@ -5,19 +6,16 @@ use chrono::{Datelike, Local}; | |||||||
| use dioxus::core_macro::rsx; | use dioxus::core_macro::rsx; | ||||||
| use dioxus::dioxus_core::Element; | use dioxus::dioxus_core::Element; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
| use dioxus_sdk::i18n::use_i18; | use dioxus_i18n::t; | ||||||
| use dioxus_sdk::translate; |  | ||||||
| use voca_rs::Voca; | use voca_rs::Voca; | ||||||
|  |  | ||||||
| #[component] | #[component] | ||||||
| pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | ||||||
|     let i18 = use_i18(); |  | ||||||
|  |  | ||||||
|     rsx! { |     rsx! { | ||||||
|         div { |         div { | ||||||
|             class: "flex flex-col", |             class: "flex flex-col", | ||||||
|             div { |             div { | ||||||
|                 class: "mt-1 grow font-medium", |                 class: "mt-2 grow font-medium", | ||||||
|                 {task.task().title()} |                 {task.task().title()} | ||||||
|             }, |             }, | ||||||
|             div { |             div { | ||||||
| @@ -33,37 +31,37 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | |||||||
|                             format!( |                             format!( | ||||||
|                                 " {}", |                                 " {}", | ||||||
|                                 if deadline == today_date - chrono::Days::new(1) { |                                 if deadline == today_date - chrono::Days::new(1) { | ||||||
|                                     translate!(i18, "yesterday") |                                     t!("yesterday") | ||||||
|                                 } else if deadline == today_date { |                                 } else if deadline == today_date { | ||||||
|                                     translate!(i18, "today") |                                     t!("today") | ||||||
|                                 } else if deadline == today_date + chrono::Days::new(1) { |                                 } else if deadline == today_date + chrono::Days::new(1) { | ||||||
|                                     translate!(i18, "tomorrow") |                                     t!("tomorrow") | ||||||
|                                 } else if deadline > today_date |                                 } else if deadline > today_date | ||||||
|                                     && deadline <= today_date + chrono::Days::new(7) { |                                     && deadline <= today_date + chrono::Days::new(7) { | ||||||
|                                     let deadline = deadline.format_localized( |                                     let deadline = deadline.format_localized( | ||||||
|                                         "%A", |                                         "%A", | ||||||
|                                         LocaleFromLanguageIdentifier::from( |                                         LocaleFromLanguageIdentifier::from( | ||||||
|                                             &(i18.selected_language)() |                                             &i18n().language() | ||||||
|                                         ).into() |                                         ).into() | ||||||
|                                     ).to_string(); |                                     ).to_string(); | ||||||
|                                     if translate!(i18, "formats.weekday_lowercase_first") |                                     if t!("weekday-lowercase-first") | ||||||
|                                         .parse().unwrap() { |                                         .parse().unwrap() { | ||||||
|                                         deadline._lower_first() |                                         deadline._lower_first() | ||||||
|                                     } else { |                                     } else { | ||||||
|                                         deadline |                                         deadline | ||||||
|                                     } |                                     } | ||||||
|                                 } else { |                                 } else { | ||||||
|                                     let format = translate!(i18, |                                     let format = t!( | ||||||
|                                         if deadline.year() == today_date.year() { |                                         if deadline.year() == today_date.year() { | ||||||
|                                             "formats.date_format" |                                             "date-format" | ||||||
|                                         } else { |                                         } else { | ||||||
|                                             "formats.date_year_format" |                                             "date-year-format" | ||||||
|                                         } |                                         } | ||||||
|                                     ); |                                     ); | ||||||
|                                     deadline.format_localized( |                                     deadline.format_localized( | ||||||
|                                         format.as_str(), |                                         format.as_str(), | ||||||
|                                         LocaleFromLanguageIdentifier::from( |                                         LocaleFromLanguageIdentifier::from( | ||||||
|                                             &(i18.selected_language)() |                                             &i18n().language() | ||||||
|                                         ).into() |                                         ).into() | ||||||
|                                     ).to_string() |                                     ).to_string() | ||||||
|                                 } |                                 } | ||||||
| @@ -79,8 +77,8 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element { | |||||||
|                                 class: "fa-solid fa-clock" |                                 class: "fa-solid fa-clock" | ||||||
|                             }, |                             }, | ||||||
|                             { |                             { | ||||||
|                                 let format = translate!(i18, "formats.time_format"); |                                 let format = t!("time-format"); | ||||||
|                                 format!(" {}",calendar_time.time().format(format.as_str())) |                                 format!(" {}", calendar_time.time().format(format.as_str())) | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								src/internationalization/cs_cz.ftl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/internationalization/cs_cz.ftl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | none = žádný | ||||||
|  | long-term = dlouhodobé | ||||||
|  | yesterday = včera | ||||||
|  | today = dnes | ||||||
|  | tomorrow = zítra | ||||||
|  | overdue = zpožděné | ||||||
|  |  | ||||||
|  | ## Date and time formats | ||||||
|  | date-format = %-d. %B | ||||||
|  | date-year-format = %-d. %B %Y | ||||||
|  | date-weekday-format = %A %-d. %B | ||||||
|  | date-weekday-year-format = %A %-d. %B %Y | ||||||
|  | weekday-lowercase-first = true | ||||||
|  | time-format = %-H:%M | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| { |  | ||||||
|   "id": "cs-CZ", |  | ||||||
|   "texts": { |  | ||||||
|     "none": "žádný", |  | ||||||
|     "long_term": "dlouhodobé", |  | ||||||
|     "yesterday": "včera", |  | ||||||
|     "today": "dnes", |  | ||||||
|     "tomorrow": "zítra", |  | ||||||
|     "overdue": "zpožděné", |  | ||||||
|     "formats": { |  | ||||||
|       "date_format": "%-d. %B", |  | ||||||
|       "date_year_format": "%-d. %B %Y", |  | ||||||
|       "date_weekday_format": "%A %-d. %B", |  | ||||||
|       "date_weekday_year_format": "%A %-d. %B %Y", |  | ||||||
|       "weekday_lowercase_first": "true", |  | ||||||
|       "time_format": "%-H:%M" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										14
									
								
								src/internationalization/en_us.ftl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/internationalization/en_us.ftl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | none = none | ||||||
|  | long-term = long-term | ||||||
|  | yesterday = yesterday | ||||||
|  | today = today | ||||||
|  | tomorrow = tomorrow | ||||||
|  | overdue = overdue | ||||||
|  |  | ||||||
|  | ## Date and time formats | ||||||
|  | date-format = %B %-d | ||||||
|  | date-year-format = %B %-d, %Y | ||||||
|  | date-weekday-format = %A, %B %-d | ||||||
|  | date-weekday-year-format = %A, %B %-d, %Y | ||||||
|  | weekday-lowercase-first = false | ||||||
|  | time-format = %-I:%M %P | ||||||
| @@ -1,19 +0,0 @@ | |||||||
| { |  | ||||||
|   "id": "en-US", |  | ||||||
|   "texts": { |  | ||||||
|     "none": "none", |  | ||||||
|     "long_term": "long-term", |  | ||||||
|     "yesterday": "yesterday", |  | ||||||
|     "today": "today", |  | ||||||
|     "tomorrow": "tomorrow", |  | ||||||
|     "overdue": "overdue", |  | ||||||
|     "formats": { |  | ||||||
|       "date_format": "%B %-d", |  | ||||||
|       "date_year_format": "%B %-d, %Y", |  | ||||||
|       "date_weekday_format": "%A, %B %-d", |  | ||||||
|       "date_weekday_year_format": "%A, %B %-d, %Y", |  | ||||||
|       "weekday_lowercase_first": "false", |  | ||||||
|       "time_format": "%-I:%M %P" |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -1,21 +1,12 @@ | |||||||
| use std::ops::Deref; | use std::ops::Deref; | ||||||
| use std::str::FromStr; |  | ||||||
| use std::sync::Mutex; | use std::sync::Mutex; | ||||||
| use chrono::Locale; | use chrono::Locale; | ||||||
| use dioxus::fullstack::once_cell::sync::Lazy; | use dioxus::fullstack::once_cell::sync::Lazy; | ||||||
| use dioxus_sdk::i18n::Language; |  | ||||||
| use feruca::Collator; | use feruca::Collator; | ||||||
| use unic_langid_impl::LanguageIdentifier; | use unic_langid_impl::LanguageIdentifier; | ||||||
|  |  | ||||||
| const EN_US: &str = include_str!("en_us.json"); |  | ||||||
| const CS_CZ: &str = include_str!("cs_cz.json"); |  | ||||||
|  |  | ||||||
| pub(crate) static COLLATOR: Lazy<Mutex<Collator>> = Lazy::new(|| Mutex::new(Collator::default())); | pub(crate) static COLLATOR: Lazy<Mutex<Collator>> = Lazy::new(|| Mutex::new(Collator::default())); | ||||||
|  |  | ||||||
| pub(crate) fn get_languages() -> Vec<Language> { |  | ||||||
|     Vec::from([EN_US, CS_CZ]).into_iter().map(|texts| Language::from_str(texts).unwrap()).collect() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub(crate) struct LocaleFromLanguageIdentifier<'a>(&'a LanguageIdentifier); | pub(crate) struct LocaleFromLanguageIdentifier<'a>(&'a LanguageIdentifier); | ||||||
|  |  | ||||||
| impl<'a> Deref for LocaleFromLanguageIdentifier<'a> { | impl<'a> Deref for LocaleFromLanguageIdentifier<'a> { | ||||||
|   | |||||||
| @@ -11,19 +11,14 @@ mod migrations; | |||||||
|  |  | ||||||
| use components::app::App; | use components::app::App; | ||||||
| use dioxus::prelude::*; | use dioxus::prelude::*; | ||||||
| use dioxus_logger::tracing::{info, Level}; | use tracing::info; | ||||||
|  |  | ||||||
| fn main() { | fn main() { | ||||||
|     dioxus_logger::init(Level::INFO).expect("Failed to initialize the logger."); |  | ||||||
|  |  | ||||||
|     info!("Running migrations."); |     info!("Running migrations."); | ||||||
|     server_only!( |     server_only!( | ||||||
|         migrations::run_migrations().expect("Failed to run migrations."); |         migrations::run_migrations().expect("Failed to run migrations."); | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     info!("Starting app."); |     info!("Starting app."); | ||||||
|     let cfg = server_only!( |     launch(App); | ||||||
|         dioxus::fullstack::Config::new().addr(std::net::SocketAddr::from(([0, 0, 0, 0], 8000))) |  | ||||||
|     ); |  | ||||||
|     LaunchBuilder::fullstack().with_cfg(cfg).launch(App); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ use dotenvy::dotenv; | |||||||
| #[server] | #[server] | ||||||
| pub(crate) async fn get_language_identifier() -> Result<LanguageIdentifier, ServerFnError> { | pub(crate) async fn get_language_identifier() -> Result<LanguageIdentifier, ServerFnError> { | ||||||
|     dotenv().expect("Could not load environment variables from the .env file."); |     dotenv().expect("Could not load environment variables from the .env file."); | ||||||
|      |  | ||||||
|     Ok(env::var("LANGUAGE_CODE") |     Ok(env::var("LANGUAGE_CODE") | ||||||
|         .expect("The environment variable LANGUAGE_CODE must be set.") |         .expect("The environment variable LANGUAGE_CODE must be set.") | ||||||
|         .parse::<LanguageIdentifier>()?) |         .parse::<LanguageIdentifier>()?) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user