aboutsummaryrefslogtreecommitdiff
path: root/src/models
diff options
context:
space:
mode:
authorGravatar Jake Swenson <jakeswenson@users.noreply.github.com> 2021-05-16 22:09:23 -0700
committerGravatar GitHub <noreply@github.com> 2021-05-16 22:09:23 -0700
commita2dc79a5079d6286ebd148cf25a00e5dd013efdc (patch)
tree116b8b9272174395568eaa699c5c73104e0b3c5e /src/models
parentfa85eb7182471a0fa15b7268e4c9adac326756f8 (diff)
downloadnotion-a2dc79a5079d6286ebd148cf25a00e5dd013efdc.tar.gz
notion-a2dc79a5079d6286ebd148cf25a00e5dd013efdc.tar.zst
notion-a2dc79a5079d6286ebd148cf25a00e5dd013efdc.zip
chore: lots of little cleanup (#7)
Diffstat (limited to 'src/models')
-rw-r--r--src/models/search.rs247
1 files changed, 223 insertions, 24 deletions
diff --git a/src/models/search.rs b/src/models/search.rs
index 8cb4327..6acf847 100644
--- a/src/models/search.rs
+++ b/src/models/search.rs
@@ -1,39 +1,50 @@
use crate::models::paging::Paging;
-use serde::{Deserialize, Serialize, Serializer};
+use crate::models::{Number, PageId, UserId};
+use chrono::{DateTime, Utc};
+use serde::ser::SerializeMap;
+use serde::{Serialize, Serializer};
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[serde(rename_all = "snake_case")]
pub enum SortDirection {
Ascending,
Descending,
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[serde(rename_all = "snake_case")]
pub enum SortTimestamp {
LastEditedTime,
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum DatabaseSortTimestamp {
+ CreatedTime,
+ LastEditedTime,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[serde(rename_all = "snake_case")]
pub enum FilterValue {
Page,
Database,
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Hash, Copy, Clone)]
#[serde(rename_all = "snake_case")]
pub enum FilterProperty {
Object,
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
pub struct Sort {
+ /// The name of the timestamp to sort against.
timestamp: SortTimestamp,
direction: SortDirection,
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
pub struct Filter {
property: FilterProperty,
value: FilterValue,
@@ -51,7 +62,7 @@ pub struct SearchRequest {
paging: Option<Paging>,
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
#[serde(rename_all = "snake_case")]
pub enum TextCondition {
Equals(String),
@@ -73,23 +84,213 @@ where
serializer.serialize_bool(true)
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
-#[serde(rename_all = "lowercase")]
+fn serialize_to_empty_object<S>(serializer: S) -> Result<S::Ok, S::Error>
+where
+ S: Serializer,
+{
+ // Todo: there has to be a better way?
+ serializer.serialize_map(Some(0))?.end()
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum NumberCondition {
+ Equals(Number),
+ DoesNotEqual(Number),
+ GreaterThan(Number),
+ LessThan(Number),
+ GreaterThanOrEqualTo(Number),
+ LessThanOrEqualTo(Number),
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum CheckboxCondition {
+ Equals(bool),
+ DoesNotEqual(bool),
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum SelectCondition {
+ /// Only return pages where the page property value matches the provided value exactly.
+ Equals(String),
+ /// Only return pages where the page property value does not match the provided value exactly.
+ DoesNotEqual(String),
+ /// Only return pages where the page property value is empty.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ /// Only return pages where the page property value is present.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum MultiSelectCondition {
+ /// Only return pages where the page property value contains the provided value.
+ Contains(String),
+ /// Only return pages where the page property value does not contain the provided value.
+ DoesNotContain(String),
+ /// Only return pages where the page property value is empty.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ /// Only return pages where the page property value is present.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum DateCondition {
+ /// Only return pages where the page property value matches the provided date exactly.
+ /// Note that the comparison is done against the date.
+ /// Any time information sent will be ignored.
+ Equals(DateTime<Utc>),
+ /// Only return pages where the page property value is before the provided date.
+ /// Note that the comparison is done against the date.
+ /// Any time information sent will be ignored.
+ Before(DateTime<Utc>),
+ /// Only return pages where the page property value is after the provided date.
+ /// Note that the comparison is done against the date.
+ /// Any time information sent will be ignored.
+ After(DateTime<Utc>),
+ /// Only return pages where the page property value is on or before the provided date.
+ /// Note that the comparison is done against the date.
+ /// Any time information sent will be ignored.
+ OnOrBefore(DateTime<Utc>),
+ /// Only return pages where the page property value is on or after the provided date.
+ /// Note that the comparison is done against the date.
+ /// Any time information sent will be ignored.
+ OnOrAfter(DateTime<Utc>),
+ /// Only return pages where the page property value is empty.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ /// Only return pages where the page property value is present.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+ /// Only return pages where the page property value is within the past week.
+ #[serde(serialize_with = "serialize_to_empty_object")]
+ PastWeek,
+ /// Only return pages where the page property value is within the past month.
+ #[serde(serialize_with = "serialize_to_empty_object")]
+ PastMonth,
+ /// Only return pages where the page property value is within the past year.
+ #[serde(serialize_with = "serialize_to_empty_object")]
+ PastYear,
+ /// Only return pages where the page property value is within the next week.
+ #[serde(serialize_with = "serialize_to_empty_object")]
+ NextWeek,
+ /// Only return pages where the page property value is within the next month.
+ #[serde(serialize_with = "serialize_to_empty_object")]
+ NextMonth,
+ /// Only return pages where the page property value is within the next year.
+ #[serde(serialize_with = "serialize_to_empty_object")]
+ NextYear,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum PeopleCondition {
+ Contains(UserId),
+ /// Only return pages where the page property value does not contain the provided value.
+ DoesNotContain(UserId),
+ /// Only return pages where the page property value is empty.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ /// Only return pages where the page property value is present.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum FilesCondition {
+ /// Only return pages where the page property value is empty.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ /// Only return pages where the page property value is present.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum RelationCondition {
+ /// Only return pages where the page property value contains the provided value.
+ Contains(PageId),
+ /// Only return pages where the page property value does not contain the provided value.
+ DoesNotContain(PageId),
+ /// Only return pages where the page property value is empty.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsEmpty,
+ /// Only return pages where the page property value is present.
+ #[serde(serialize_with = "serialize_to_true")]
+ IsNotEmpty,
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum FormulaCondition {
+ /// Only return pages where the result type of the page property formula is "text"
+ /// and the provided text filter condition matches the formula's value.
+ Text(TextCondition),
+ /// Only return pages where the result type of the page property formula is "number"
+ /// and the provided number filter condition matches the formula's value.
+ Number(NumberCondition),
+ /// Only return pages where the result type of the page property formula is "checkbox"
+ /// and the provided checkbox filter condition matches the formula's value.
+ Checkbox(CheckboxCondition),
+ /// Only return pages where the result type of the page property formula is "date"
+ /// and the provided date filter condition matches the formula's value.
+ Date(DateCondition),
+}
+
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+#[serde(rename_all = "snake_case")]
pub enum PropertyCondition {
Text(TextCondition),
+ Number(NumberCondition),
+ Checkbox(CheckboxCondition),
+ Select(SelectCondition),
+ MultiSelect(MultiSelectCondition),
+ Date(DateCondition),
+ People(PeopleCondition),
+ Files(FilesCondition),
+ Relation(RelationCondition),
+ Formula(FormulaCondition),
+ /// Returns pages when **any** of the filters inside the provided vector match.
+ Or(Vec<PropertyCondition>),
+ /// Returns pages when **all** of the filters inside the provided vector match.
+ And(Vec<PropertyCondition>),
}
-#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
pub struct FilterCondition {
pub property: String,
#[serde(flatten)]
pub condition: PropertyCondition,
}
+#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
+pub struct DatabaseSort {
+ // Todo: Should property and timestamp be mutually exclusive? (i.e a flattened enum?)
+ // the documentation is not clear:
+ // https://developers.notion.com/reference/post-database-query#post-database-query-sort
+ property: Option<String>,
+ /// The name of the timestamp to sort against.
+ timestamp: Option<SortTimestamp>,
+ direction: SortDirection,
+}
+
#[derive(Serialize, Debug, Eq, PartialEq, Default)]
pub struct DatabaseQuery {
#[serde(skip_serializing_if = "Option::is_none")]
- pub sorts: Option<Sort>,
+ pub sorts: Option<Vec<DatabaseSort>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub filter: Option<FilterCondition>,
#[serde(flatten)]
@@ -138,31 +339,29 @@ impl From<NotionSearch> for SearchRequest {
mod tests {
mod text_filters {
use crate::models::search::PropertyCondition::Text;
- use crate::models::search::{FilterCondition, PropertyCondition, TextCondition};
+ use crate::models::search::{FilterCondition, TextCondition};
+ use serde_json::json;
#[test]
fn text_property_equals() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_string(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition {
property: "Name".to_string(),
condition: Text(TextCondition::Equals("Test".to_string())),
})?;
- assert_eq!(
- dbg!(json),
- r#"{"property":"Name","text":{"equals":"Test"}}"#
- );
+ assert_eq!(json, json!({"property":"Name","text":{"equals":"Test"}}));
Ok(())
}
#[test]
fn text_property_contains() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_string(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition {
property: "Name".to_string(),
condition: Text(TextCondition::Contains("Test".to_string())),
})?;
assert_eq!(
dbg!(json),
- r#"{"property":"Name","text":{"contains":"Test"}}"#
+ json!({"property":"Name","text":{"contains":"Test"}})
);
Ok(())
@@ -170,13 +369,13 @@ mod tests {
#[test]
fn text_property_is_empty() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_string(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition {
property: "Name".to_string(),
condition: Text(TextCondition::IsEmpty),
})?;
assert_eq!(
dbg!(json),
- r#"{"property":"Name","text":{"is_empty":true}}"#
+ json!({"property":"Name","text":{"is_empty":true}})
);
Ok(())
@@ -184,13 +383,13 @@ mod tests {
#[test]
fn text_property_is_not_empty() -> Result<(), Box<dyn std::error::Error>> {
- let json = serde_json::to_string(&FilterCondition {
+ let json = serde_json::to_value(&FilterCondition {
property: "Name".to_string(),
condition: Text(TextCondition::IsNotEmpty),
})?;
assert_eq!(
dbg!(json),
- r#"{"property":"Name","text":{"is_not_empty":true}}"#
+ json!({"property":"Name","text":{"is_not_empty":true}})
);
Ok(())