#[cfg(feature = "server")] use crate::models::task::Task; #[cfg(feature = "server")] use crate::schema::subtasks; use chrono::NaiveDateTime; #[cfg(feature = "server")] use diesel::prelude::*; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use validator::Validate; const TITLE_LENGTH_MIN: u64 = 1; const TITLE_LENGTH_MAX: u64 = 255; #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] #[cfg_attr( feature = "server", derive(Queryable, Selectable, Identifiable, Associations) )] #[cfg_attr( feature = "server", diesel( table_name = subtasks, belongs_to(Task, foreign_key = task_id), check_for_backend(diesel::pg::Pg) ) )] pub struct Subtask { id: i32, task_id: i32, title: String, is_completed: bool, created_at: NaiveDateTime, updated_at: NaiveDateTime, } impl Subtask { pub fn id(&self) -> i32 { self.id } pub fn task_id(&self) -> i32 { self.task_id } pub fn title(&self) -> &str { &self.title } pub fn is_completed(&self) -> bool { self.is_completed } pub fn created_at(&self) -> NaiveDateTime { self.created_at } pub fn updated_at(&self) -> NaiveDateTime { self.updated_at } } impl Eq for Subtask {} impl PartialOrd for Subtask { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for Subtask { fn cmp(&self, other: &Self) -> Ordering { self.is_completed() .cmp(&other.is_completed()) .then(self.created_at().cmp(&other.created_at())) } } #[derive(Serialize, Deserialize, Validate, Clone, Debug)] #[cfg_attr(feature = "server", derive(Insertable))] #[cfg_attr(feature = "server", diesel(table_name = subtasks))] pub struct NewSubtask { pub task_id: i32, #[validate(length( min = "TITLE_LENGTH_MIN", max = "TITLE_LENGTH_MAX", code = "title_length" ))] pub title: String, pub is_completed: bool, } impl NewSubtask { pub fn new(task_id: i32, title: String, is_completed: bool) -> Self { Self { task_id, title, is_completed, } } } impl From for NewSubtask { fn from(subtask: Subtask) -> Self { Self::new(subtask.task_id, subtask.title, subtask.is_completed) } }