notionrs_schema/object/page/
files.rs

1use serde::{Deserialize, Serialize};
2
3/// <https://developers.notion.com/reference/page-property-values#files>
4///
5/// - `$.['*'].id`: An underlying identifier for the property.
6///   `id` remains constant when the property name changes.
7/// - `$.['*'].type`: Always `"files"`
8/// - `$.['*'].files`: An array of objects containing information about
9///   the [files](https://developers.notion.com/reference/file-object).
10///   If the file does not exist, an empty array will be returned.
11///
12/// **Note**: The `['*']` part represents the column name you set when creating the database.
13///
14/// Example files page property value
15///
16/// ```json
17/// {
18///   "Files & media": {
19///     "id": "Q%7Dn%3E",
20///     "type": "files",
21///     "files": [
22///       {
23///         "name": "Project Alpha blueprint",
24///         "type": "file",
25///         "file": {
26///           "url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/daa95f86-2d56-4e18-be3b-16d81b31dc0d",
27///           "expiry_time": "2024-04-04T10:45:54.308Z"
28///         }
29///       }
30///     ]
31///   }
32/// }
33/// ```
34#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default, notionrs_macro::Setter)]
35pub struct PageFilesProperty {
36    /// An underlying identifier for the property.
37    /// `id` remains constant when the property name changes.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub id: Option<String>,
40
41    /// An array of objects containing information
42    /// about the [files](https://developers.notion.com/reference/file-object).
43    ///
44    /// When creating, both the external path of the file and `name` are required.
45    pub files: Vec<crate::object::file::File>,
46}
47
48impl<T> From<T> for PageFilesProperty
49where
50    T: AsRef<str>,
51{
52    fn from(value: T) -> Self {
53        let file = crate::object::file::File::default()
54            .url(value.as_ref())
55            .name(value.as_ref());
56        Self::default().files(vec![file])
57    }
58}
59
60impl From<crate::object::file::File> for PageFilesProperty {
61    fn from(value: crate::object::file::File) -> Self {
62        Self::default().files(vec![value])
63    }
64}
65
66impl std::fmt::Display for PageFilesProperty {
67    /// display the files' names in a comma-separated list
68    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
69        write!(
70            f,
71            "{}",
72            self.files
73                .iter()
74                .map(|file| file.to_string())
75                .collect::<Vec<String>>()
76                .join(", ")
77        )
78    }
79}
80
81// # --------------------------------------------------------------------------------
82//
83// unit test
84//
85// # --------------------------------------------------------------------------------
86
87#[cfg(test)]
88mod unit_tests {
89
90    use super::*;
91
92    #[test]
93    fn deserialize_page_files_property() {
94        let json_data = r#"
95        {
96            "File": {
97                "id": "%3AlnV",
98                "type": "files",
99                "files": [
100                    {
101                        "name": "0208a.jpg",
102                        "type": "file",
103                        "file": {
104                            "url": "https://prod-files-secure.s3.us-west-2.amazonaws.com",
105                            "expiry_time": "2024-08-15T05:56:14.346Z"
106                        }
107                    },
108                    {
109                        "name": "Favicon.ico",
110                        "type": "external",
111                        "external": {
112                            "url": "https://www.notion.so/images/favicon.ico"
113                        }
114                    }
115                ]
116            }
117        }
118        "#;
119
120        let file_map =
121            serde_json::from_str::<std::collections::HashMap<String, PageFilesProperty>>(json_data)
122                .unwrap();
123
124        let file = file_map.get("File").unwrap();
125
126        assert_eq!(file.id, Some("%3AlnV".to_string()));
127
128        for file in &file.files {
129            match &file {
130                crate::object::file::File::Uploaded(f) => {
131                    assert_eq!(f.name, Some("0208a.jpg".to_string()));
132                    assert_eq!(
133                        f.file.url,
134                        "https://prod-files-secure.s3.us-west-2.amazonaws.com"
135                    );
136                    assert_eq!(f.file.expiry_time, "2024-08-15T05:56:14.346Z");
137                }
138                crate::object::file::File::External(f) => {
139                    assert_eq!(f.name, Some("Favicon.ico".to_string()));
140                    assert_eq!(f.external.url, "https://www.notion.so/images/favicon.ico");
141                }
142            }
143        }
144    }
145}