feat: sort projects by title internationally
This commit is contained in:
		| @@ -6,15 +6,15 @@ use crate::models::task::NewTask; | |||||||
| use crate::models::task::Task; | use crate::models::task::Task; | ||||||
| use crate::query::{QueryErrors, QueryKey, QueryValue}; | use crate::query::{QueryErrors, QueryKey, QueryValue}; | ||||||
| use crate::route::Route; | use crate::route::Route; | ||||||
| use crate::server::projects::get_projects; |  | ||||||
| use crate::server::tasks::{create_task, delete_task, edit_task}; | use crate::server::tasks::{create_task, delete_task, edit_task}; | ||||||
| use chrono::Duration; | 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_query::prelude::use_query_client; | use dioxus_query::prelude::{use_query_client, QueryResult}; | ||||||
| use dioxus_sdk::i18n::use_i18; | use dioxus_sdk::i18n::use_i18; | ||||||
| use dioxus_sdk::translate; | use dioxus_sdk::translate; | ||||||
|  | use crate::query::projects::use_projects_query; | ||||||
|  |  | ||||||
| const REMINDER_OFFSETS: [Option<Duration>; 17] = [ | const REMINDER_OFFSETS: [Option<Duration>; 17] = [ | ||||||
|     None, |     None, | ||||||
| @@ -38,25 +38,25 @@ const REMINDER_OFFSETS: [Option<Duration>; 17] = [ | |||||||
|  |  | ||||||
| #[component] | #[component] | ||||||
| pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()>) -> Element { | pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()>) -> Element { | ||||||
|     let projects = use_server_future(get_projects)?.unwrap().unwrap(); |     let projects_query = use_projects_query(); | ||||||
|  |  | ||||||
|     let route = use_route::<Route>(); |     let route = use_route::<Route>(); | ||||||
|     let selected_category = use_signal(|| if let Some(task) = &task { |     let selected_category = use_signal(|| if let Some(task) = &task { | ||||||
|         task.category().clone() |             task.category().clone() | ||||||
|     } else { |         } else { | ||||||
|         match route { |             match route { | ||||||
|             Route::CategorySomedayMaybePage => Category::SomedayMaybe, |                 Route::CategorySomedayMaybePage => Category::SomedayMaybe, | ||||||
|             Route::CategoryWaitingForPage => Category::WaitingFor(String::new()), |                 Route::CategoryWaitingForPage => Category::WaitingFor(String::new()), | ||||||
|             Route::CategoryNextStepsPage => Category::NextSteps, |                 Route::CategoryNextStepsPage => Category::NextSteps, | ||||||
|             Route::CategoryCalendarPage | Route::CategoryTodayPage => Category::Calendar { |                 Route::CategoryCalendarPage | Route::CategoryTodayPage => Category::Calendar { | ||||||
|                 date: chrono::Local::now().date_naive(), |                     date: chrono::Local::now().date_naive(), | ||||||
|                 reoccurrence: None, |                     reoccurrence: None, | ||||||
|                 time: None, |                     time: None, | ||||||
|             }, |                 }, | ||||||
|             Route::CategoryLongTermPage => Category::LongTerm, |                 Route::CategoryLongTermPage => Category::LongTerm, | ||||||
|             _ => Category::Inbox, |                 _ => Category::Inbox, | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |  | ||||||
|     ); |     ); | ||||||
|     let category_calendar_reoccurrence_interval = use_signal(|| task.as_ref().and_then(|task| |     let category_calendar_reoccurrence_interval = use_signal(|| task.as_ref().and_then(|task| | ||||||
|         if let Category::Calendar { reoccurrence: Some(reoccurrence), .. } = task.category() { |         if let Category::Calendar { reoccurrence: Some(reoccurrence), .. } = task.category() { | ||||||
| @@ -178,14 +178,32 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<() | |||||||
|                             value: 0, |                             value: 0, | ||||||
|                             {translate!(i18, "none")} |                             {translate!(i18, "none")} | ||||||
|                         }, |                         }, | ||||||
|                         for project in projects { |                         match projects_query.result().value() { | ||||||
|                             option { |                             QueryResult::Ok(QueryValue::Projects(projects)) | ||||||
|                                 value: project.id().to_string(), |                             | QueryResult::Loading(Some(QueryValue::Projects(projects))) => { | ||||||
|                                 initial_selected: task.as_ref().is_some_and( |                                 let mut projects = projects.clone(); | ||||||
|                                     |task| task.project_id() == Some(project.id()) |                                 projects.sort(); | ||||||
|                                 ), |                                 rsx! { | ||||||
|                                 {project.title()} |                                     for project in projects { | ||||||
|                             } |                                         option { | ||||||
|  |                                             value: project.id().to_string(), | ||||||
|  |                                             initial_selected: task.as_ref().is_some_and( | ||||||
|  |                                                 |task| task.project_id() == Some(project.id()) | ||||||
|  |                                             ), | ||||||
|  |                                             {project.title()} | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                             QueryResult::Loading(None) => rsx! { | ||||||
|  |                                 // TODO: Add a loading indicator. | ||||||
|  |                             }, | ||||||
|  |                             QueryResult::Err(errors) => rsx! { | ||||||
|  |                                 div { | ||||||
|  |                                     "Errors occurred: {errors:?}" | ||||||
|  |                                 } | ||||||
|  |                             }, | ||||||
|  |                             value => panic!("Unexpected query result: {value:?}") | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                 }, |                 }, | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ use std::cmp::Ordering; | |||||||
| use chrono::NaiveDateTime; | use chrono::NaiveDateTime; | ||||||
| use crate::schema::projects; | use crate::schema::projects; | ||||||
| use diesel::prelude::*; | use diesel::prelude::*; | ||||||
|  | use feruca::Collator; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
| use validator::Validate; | use validator::Validate; | ||||||
|  |  | ||||||
| @@ -46,7 +47,7 @@ impl PartialOrd<Self> for Project { | |||||||
|  |  | ||||||
| impl Ord for Project { | impl Ord for Project { | ||||||
|     fn cmp(&self, other: &Self) -> Ordering { |     fn cmp(&self, other: &Self) -> Ordering { | ||||||
|         self.title().cmp(other.title()) |         Collator::default().collate(self.title(), other.title()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Matouš Volf
					Matouš Volf