summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Murphy <hello@itsjamie.dev>2023-02-11 23:02:33 -0800
committerJamie Murphy <hello@itsjamie.dev>2023-02-12 07:14:41 +0000
commit1c2b5f0b327e95c18ccb2322c79c8a5987c3c888 (patch)
treebabd4974d17d1227e3e3789c277c8754103cb23e
parent68c617e5f8aba7ff3b3d8b81394fa9121cf0a1c0 (diff)
downloadgnome-todo-1c2b5f0b327e95c18ccb2322c79c8a5987c3c888.tar.gz
task: Setup Task for being used with Diesel
Implement the Queryable trait, as well as fix some properties to match the database
-rw-r--r--src/engine/task.rs116
1 files changed, 91 insertions, 25 deletions
diff --git a/src/engine/task.rs b/src/engine/task.rs
index 3a14a17c..7f987262 100644
--- a/src/engine/task.rs
+++ b/src/engine/task.rs
@@ -1,10 +1,12 @@
+use chrono::NaiveDateTime;
+use diesel::{sqlite::Sqlite, Queryable};
use gtk::{
glib::{self, Object},
prelude::*,
subclass::prelude::*,
};
-use crate::utils::Iso8601;
+use crate::{schema, utils::Iso8601};
/// The task's priority.
/// For more details please view RFC 5545, section 3.8.1.9
@@ -45,18 +47,18 @@ mod imp {
pub struct Task {
// summary, RFC 5545, 3.8.1.12
#[property(get, set)]
- pub title: RefCell<String>,
+ pub title: RefCell<Option<String>>,
// description, RFC 5545, 3.8.1.5
#[property(get, set)]
- pub description: RefCell<String>,
+ pub description: RefCell<Option<String>>,
// due, RFC 5545, 3.8.2.3
- #[property(get = Self::due_date, set = Self::set_due_date, type = String)]
- pub due_date: Cell<NaiveDateTime>,
+ #[property(get = Self::due_date, set = Self::set_due_date, type = Option<String>)]
+ pub due_date: Cell<Option<NaiveDateTime>>,
// completed, RFC 5545, 3.8.2.1
- #[property(get = Self::completed, set = Self::set_completed, type = String)]
- pub completed: Cell<NaiveDateTime>,
+ #[property(get = Self::completed, set = Self::set_completed, type = Option<String>)]
+ pub completed: Cell<Option<NaiveDateTime>>,
// priority, RFC 5545, 3.8.1.9
- #[property(get, set)]
+ #[property(get, set, default = 9)] // so apparently this macro doesn't like default = 9
pub priority: Cell<i32>,
// created, RFC 5545, 3.8.7.1
#[property(get = Self::created, set = Self::set_created, type = String)]
@@ -92,26 +94,26 @@ mod imp {
}
impl Task {
- fn due_date(&self) -> String {
- self.due_date.get().to_iso8601()
+ fn due_date(&self) -> Option<String> {
+ self.due_date.get().map(|s| s.to_iso8601())
}
fn set_due_date(&self, value: String) {
- self.due_date.replace(
- NaiveDateTime::parse_from_iso8601(&value)
- .expect("The value needs to be in a format recognizable by ISO8601"),
- );
+ self.due_date
+ .replace(Some(NaiveDateTime::parse_from_iso8601(&value).expect(
+ "The value needs to be in a format recognizable by ISO8601",
+ )));
}
- fn completed(&self) -> String {
- self.completed.get().to_iso8601()
+ fn completed(&self) -> Option<String> {
+ self.completed.get().map(|s| s.to_iso8601())
}
fn set_completed(&self, value: String) {
- self.completed.replace(
- NaiveDateTime::parse_from_iso8601(&value)
- .expect("The value needs to be in a format recognizable by ISO8601"),
- );
+ self.completed
+ .replace(Some(NaiveDateTime::parse_from_iso8601(&value).expect(
+ "The value needs to be in a format recognizable by ISO8601",
+ )));
}
fn created(&self) -> String {
@@ -142,12 +144,46 @@ glib::wrapper! {
pub struct Task(ObjectSubclass<imp::Task>);
}
-impl Task {
- #![allow(clippy::new_without_default)]
-
+impl Default for Task {
/// Create a new Task
- pub fn new() -> Self {
- Object::new::<Self>()
+ /// The `created`, `last-modified`, and `modification-count` properties
+ /// are preset using this method and do not need to be set again. Use `new`
+ /// to create a Task with no defaults
+ fn default() -> Self {
+ let current_time = chrono::Utc::now().naive_utc().to_iso8601();
+ Object::builder()
+ .property("priority", 9) // so we'll add the priority here
+ .property("created", current_time.clone())
+ .property("last-modified", current_time)
+ .property("modification-count", 0)
+ .build()
+ }
+}
+
+impl Task {
+ #![allow(clippy::too_many_arguments)]
+
+ /// Create a new Task with values from a database
+ pub fn new(
+ title: Option<String>,
+ description: Option<String>,
+ due_date: Option<NaiveDateTime>,
+ completed: Option<NaiveDateTime>,
+ priority: Option<i32>,
+ created: NaiveDateTime,
+ last_modified: NaiveDateTime,
+ modification_count: i32,
+ ) -> Self {
+ Object::builder()
+ .property("title", title)
+ .property("description", description)
+ .property("due_date", due_date.map(|s| s.to_iso8601()))
+ .property("completed", completed.map(|s| s.to_iso8601()))
+ .property("priority", priority.unwrap_or(9))
+ .property("created", created.to_iso8601())
+ .property("last_modified", last_modified.to_iso8601())
+ .property("modification_count", modification_count)
+ .build()
}
/// Create a UID for the Task.
@@ -160,3 +196,33 @@ impl Task {
format!("{date}@ENDEAVOUR")
}
}
+
+impl Queryable<schema::tasks::SqlType, Sqlite> for Task {
+ type Row = (
+ String, // id
+ Option<String>, // title
+ Option<String>, // description
+ Option<String>, // due_date
+ Option<String>, // completed
+ Option<i32>, // priority
+ String, // created
+ String, // last_modified
+ i32, // modification_count
+ Option<i32>, // list
+ );
+
+ fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
+ Ok(Self::new(
+ row.1,
+ row.2,
+ row.3
+ .map(|s| NaiveDateTime::parse_from_iso8601(&s).expect("Expected NaiveDateTime")),
+ row.4
+ .map(|s| NaiveDateTime::parse_from_iso8601(&s).expect("Expected NaiveDateTime")),
+ row.5,
+ NaiveDateTime::parse_from_iso8601(&row.6).expect("Expected NaiveDateTime"),
+ NaiveDateTime::parse_from_iso8601(&row.7).expect("Expected NaiveDateTime"),
+ row.8,
+ ))
+ }
+}