From c9266553610fd48a66048d9169da4703a0c71716 Mon Sep 17 00:00:00 2001 From: Jake Swenson Date: Sat, 28 Aug 2021 10:14:39 -0700 Subject: [PATCH] Number format parsing bug. Fixes #15 (#16) --- src/lib.rs | 2 +- src/models.rs | 68 +++++++++++---------- src/models/paging.rs | 4 +- src/models/properties.rs | 104 +++++++++++++++++---------------- src/models/search.rs | 11 ++++ src/models/tests/issue_15.json | 89 ++++++++++++++++++++++++++++ src/models/text.rs | 36 ++++++------ 7 files changed, 212 insertions(+), 102 deletions(-) create mode 100644 src/models/tests/issue_15.json diff --git a/src/lib.rs b/src/lib.rs index 28fd426..cba9091 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ impl NotionApi { } /// Search all pages in notion. - /// Query: can either be a [SearchRequest] or a + /// `query` can either be a [SearchRequest] or a slightly more convenient /// [NotionSearch](models::search::NotionSearch) query. pub async fn search>( &self, diff --git a/src/models.rs b/src/models.rs index 78ad105..fc31d17 100644 --- a/src/models.rs +++ b/src/models.rs @@ -39,17 +39,17 @@ impl Display for DatabaseId { } /// Represents a Notion Database -/// See https://developers.notion.com/reference/database +/// See #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Database { /// Unique identifier for the database. - id: DatabaseId, + pub id: DatabaseId, /// Date and time when this database was created. - created_time: DateTime, + pub created_time: DateTime, /// Date and time when this database was updated. - last_edited_time: DateTime, + pub last_edited_time: DateTime, /// Name of the database as it appears in Notion. - title: Vec, + pub title: Vec, /// Schema of properties for the database as they appear in Notion. // // key string @@ -57,7 +57,7 @@ pub struct Database { // // value object // A Property object. - properties: HashMap, + pub properties: HashMap, } impl AsIdentifier for Database { @@ -75,7 +75,7 @@ impl Database { } } -/// https://developers.notion.com/reference/pagination#responses +/// #[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)] pub struct ListResponse { pub results: Vec, @@ -137,51 +137,51 @@ pub enum Parent { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Properties { #[serde(flatten)] - properties: HashMap, + pub properties: HashMap, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Page { - id: PageId, + pub id: PageId, /// Date and time when this page was created. - created_time: DateTime, + pub created_time: DateTime, /// Date and time when this page was updated. - last_edited_time: DateTime, + pub last_edited_time: DateTime, /// The archived status of the page. - archived: bool, - properties: Properties, - parent: Parent, + pub archived: bool, + pub properties: Properties, + pub parent: Parent, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct BlockCommon { - id: BlockId, - created_time: DateTime, - last_edited_time: DateTime, - has_children: bool, + pub id: BlockId, + pub created_time: DateTime, + pub last_edited_time: DateTime, + pub has_children: bool, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct TextAndChildren { - text: Vec, - children: Option>, + pub text: Vec, + pub children: Option>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Text { - text: Vec, + pub text: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ToDoFields { - text: Vec, - checked: bool, - children: Option>, + pub text: Vec, + pub checked: bool, + pub children: Option>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct ChildPageFields { - title: String, + pub title: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] @@ -339,19 +339,19 @@ impl UserId { #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct UserCommon { - id: UserId, - name: Option, - avatar_url: Option, + pub id: UserId, + pub name: Option, + pub avatar_url: Option, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct Person { - email: String, + pub email: String, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] pub struct Bot { - email: String, + pub email: String, } #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] @@ -371,7 +371,7 @@ pub enum User { #[cfg(test)] mod tests { - use crate::models::{ListResponse, Page}; + use crate::models::{ListResponse, Object, Page}; #[test] fn deserialize_page() { @@ -383,4 +383,10 @@ mod tests { let _page: ListResponse = serde_json::from_str(include_str!("models/tests/query_result.json")).unwrap(); } + + #[test] + fn deserialize_number_format() { + let _search_results: ListResponse = + serde_json::from_str(include_str!("models/tests/issue_15.json")).unwrap(); + } } diff --git a/src/models/paging.rs b/src/models/paging.rs index 31244a2..3b97301 100644 --- a/src/models/paging.rs +++ b/src/models/paging.rs @@ -7,7 +7,7 @@ pub struct PagingCursor(String); #[derive(Serialize, Debug, Eq, PartialEq, Default)] pub struct Paging { #[serde(skip_serializing_if = "Option::is_none")] - start_cursor: Option, + pub start_cursor: Option, #[serde(skip_serializing_if = "Option::is_none")] - page_size: Option, + pub page_size: Option, } diff --git a/src/models/properties.rs b/src/models/properties.rs index 22689e9..b3948b4 100644 --- a/src/models/properties.rs +++ b/src/models/properties.rs @@ -9,8 +9,7 @@ use super::{DateTime, Number, Utc}; pub struct PropertyId(String); /// How the number is displayed in Notion. -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone)] -#[serde(tag = "type")] +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone, Hash)] #[serde(rename_all = "snake_case")] pub enum NumberFormat { Number, @@ -26,6 +25,11 @@ pub enum NumberFormat { Yuan, } +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone)] +pub struct NumberDetails { + pub format: NumberFormat, +} + #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)] #[serde(transparent)] pub struct SelectOptionId(String); @@ -47,37 +51,37 @@ pub enum Color { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct SelectOption { - name: String, - id: SelectOptionId, - color: Color, + pub name: String, + pub id: SelectOptionId, + pub color: Color, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Select { /// Sorted list of options available for this property. - options: Vec, + pub options: Vec, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Formula { /// Formula to evaluate for this property - expression: String, + pub expression: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Relation { /// The database this relation refers to. /// New linked pages must belong to this database in order to be valid. - database_id: DatabaseId, + pub database_id: DatabaseId, /// By default, relations are formed as two synced properties across databases: /// if you make a change to one property, it updates the synced property at the same time. /// `synced_property_name` refers to the name of the property in the related database. - synced_property_name: Option, + pub synced_property_name: Option, /// By default, relations are formed as two synced properties across databases: /// if you make a change to one property, it updates the synced property at the same time. /// `synced_property_id` refers to the id of the property in the related database. /// This is usually a short string of random letters and symbols. - synced_property_id: Option, + pub synced_property_id: Option, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone)] @@ -101,17 +105,17 @@ pub enum RollupFunction { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Rollup { /// The name of the relation property this property is responsible for rolling up. - relation_property_name: String, + pub relation_property_name: String, /// The id of the relation property this property is responsible for rolling up. - relation_property_id: PropertyId, + pub relation_property_id: PropertyId, /// The name of the property of the pages in the related database /// that is used as an input to `function`. - rollup_property_name: String, + pub rollup_property_name: String, /// The id of the property of the pages in the related database /// that is used as an input to `function`. - rollup_property_id: String, + pub rollup_property_id: String, /// The function that is evaluated for every page in the relation of the rollup. - function: RollupFunction, + pub function: RollupFunction, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] @@ -119,80 +123,80 @@ pub struct Rollup { #[serde(rename_all = "snake_case")] pub enum PropertyConfiguration { /// Represents the special Title property required on every database. - /// See https://developers.notion.com/reference/database#title-configuration + /// See Title { id: PropertyId }, /// Represents a Text property - /// https://developers.notion.com/reference/database#text-configuration + /// #[serde(rename = "rich_text")] Text { id: PropertyId }, /// Represents a Number Property - /// See https://developers.notion.com/reference/database#number-configuration + /// See Number { id: PropertyId, /// How the number is displayed in Notion. - format: NumberFormat, + number: NumberDetails, }, /// Represents a Select Property - /// See https://developers.notion.com/reference/database#select-configuration + /// See Select { id: PropertyId, select: Select }, /// Represents a Multi-select Property - /// See https://developers.notion.com/reference/database#multi-select-configuration + /// See MultiSelect { id: PropertyId, multi_select: Select, }, /// Represents a Date Property - /// See https://developers.notion.com/reference/database#date-configuration + /// See Date { id: PropertyId }, /// Represents a People Property - /// See https://developers.notion.com/reference/database#people-configuration + /// See People { id: PropertyId }, /// Represents a File Property - /// See https://developers.notion.com/reference/database#file-configuration + /// See // Todo: File a bug with notion // Documentation issue: docs claim type name is `file` but it is in fact `files` Files { id: PropertyId }, /// Represents a Checkbox Property - /// See https://developers.notion.com/reference/database#checkbox-configuration + /// See Checkbox { id: PropertyId }, /// Represents a URL Property - /// See https://developers.notion.com/reference/database#url-configuration + /// See Url { id: PropertyId }, /// Represents a Email Property - /// See https://developers.notion.com/reference/database#email-configuration + /// See Email { id: PropertyId }, /// Represents a Phone number Property - /// See https://developers.notion.com/reference/database#phone-number-configuration + /// See PhoneNumber { id: PropertyId }, - /// See https://developers.notion.com/reference/database#formula-configuration + /// See Formula { id: PropertyId, formula: Formula }, - /// See https://developers.notion.com/reference/database#relation-configuration + /// See Relation { id: PropertyId, relation: Relation }, - /// See https://developers.notion.com/reference/database#rollup-configuration + /// See Rollup { id: PropertyId, rollup: Rollup }, - /// See https://developers.notion.com/reference/database#created-time-configuration + /// See CreatedTime { id: PropertyId }, - /// See https://developers.notion.com/reference/database#created-by-configuration + /// See CreatedBy { id: PropertyId }, - /// See https://developers.notion.com/reference/database#last-edited-time-configuration + /// See LastEditTime { id: PropertyId }, - /// See https://developers.notion.com/reference/database#last-edited-by-configuration + /// See LastEditBy { id: PropertyId }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct SelectedValue { - id: SelectOptionId, - name: String, - color: Color, + pub id: SelectOptionId, + pub name: String, + pub color: Color, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct DateValue { // Todo: Will this work with dates (without time)? // does there need to be an enum of Date|DateTime? - start: DateTime, - end: Option>, + pub start: DateTime, + pub end: Option>, } /// Formula property value objects represent the result of evaluating a formula @@ -212,7 +216,7 @@ pub enum FormulaResultValue { /// with a string value (UUIDv4) corresponding to a page ID in another database. #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct RelationValue { - id: PageId, + pub id: PageId, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] @@ -228,32 +232,32 @@ pub enum RollupValue { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct FileReference { - name: String, - url: String, - mime_type: String, + pub name: String, + pub url: String, + pub mime_type: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum PropertyValue { - // https://developers.notion.com/reference/page#title-property-values + // Title { id: PropertyId, title: Vec, }, - /// https://developers.notion.com/reference/page#rich-text-property-values + /// #[serde(rename = "rich_text")] Text { id: PropertyId, rich_text: Vec, }, - /// https://developers.notion.com/reference/page#number-property-values + /// Number { id: PropertyId, number: Number, }, - /// https://developers.notion.com/reference/page#select-property-values + /// Select { id: PropertyId, select: SelectedValue, @@ -266,12 +270,12 @@ pub enum PropertyValue { id: PropertyId, date: DateValue, }, - /// https://developers.notion.com/reference/page#formula-property-values + /// Formula { id: PropertyId, formula: FormulaResultValue, }, - /// https://developers.notion.com/reference/page#relation-property-values + /// Relation { id: PropertyId, relation: RelationValue, diff --git a/src/models/search.rs b/src/models/search.rs index ffcac1d..aa2f62e 100644 --- a/src/models/search.rs +++ b/src/models/search.rs @@ -299,13 +299,24 @@ pub struct DatabaseQuery { #[derive(Debug, Eq, PartialEq)] pub enum NotionSearch { + /// When supplied, limits which pages are returned by comparing the query to the page title. Query(String), + /// When supplied, sorts the results based on the provided criteria. + /// + /// Limitation: Currently only a single sort is allowed and is limited to `last_edited_time` Sort { timestamp: SortTimestamp, direction: SortDirection, }, + /// When supplied, filters the results based on the provided criteria. + /// + /// Limitation: Currently the only filter allowed is `object` which will filter by type of object (either page or database) Filter { + /// The name of the property to filter by. + /// Currently the only property you can filter by is the `object` type. property: FilterProperty, + /// The value of the property to filter the results by. + /// Possible values for object type include `page` or `database`. value: FilterValue, }, } diff --git a/src/models/tests/issue_15.json b/src/models/tests/issue_15.json new file mode 100644 index 0000000..7ca0615 --- /dev/null +++ b/src/models/tests/issue_15.json @@ -0,0 +1,89 @@ +{ + "object": "list", + "results": [ + { + "object": "database", + "id": "58be2827-5ca0-4cc4-85a8-ff656911df67", + "created_time": "2021-03-07T19:20:00.000Z", + "last_edited_time": "2021-07-11T22:04:00.000Z", + "title": [ + { + "type": "text", + "text": { "content": "Movie Collection", "link": null }, + "annotations": { + "bold": false, + "italic": false, + "strikethrough": false, + "underline": false, + "code": false, + "color": "default" + }, + "plain_text": "Movie Collection", + "href": null + } + ], + "properties": { + "Watched": { "id": " #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] -struct Annotations { - bold: Option, - code: Option, - color: Option, - italic: Option, - strikethrough: Option, - underline: Option, +pub struct Annotations { + pub bold: Option, + pub code: Option, + pub color: Option, + pub italic: Option, + pub strikethrough: Option, + pub underline: Option, } /// Properties common on all rich text objects -/// See https://developers.notion.com/reference/rich-text#all-rich-text +/// See #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct RichTextCommon { - plain_text: String, - href: Option, - annotations: Option, + pub plain_text: String, + pub href: Option, + pub annotations: Option, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct Link { - url: String, + pub url: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)] pub struct Text { - content: String, - link: Option, + pub content: String, + pub link: Option, } /// Rich text objects contain data for displaying formatted text, mentions, and equations. @@ -64,18 +64,18 @@ pub struct Text { #[serde(tag = "type")] #[serde(rename_all = "snake_case")] pub enum RichText { - /// See https://developers.notion.com/reference/rich-text#text-objects + /// See Text { #[serde(flatten)] rich_text: RichTextCommon, text: Text, }, - /// See https://developers.notion.com/reference/rich-text#mention-objects + /// See Mention { #[serde(flatten)] rich_text: RichTextCommon, }, - /// See https://developers.notion.com/reference/rich-text#equation-objects + /// See Equation { #[serde(flatten)] rich_text: RichTextCommon,