1use crate::models::text::RichText;
2use crate::models::users::User;
3
4use crate::ids::{DatabaseId, PageId, PropertyId};
5use crate::models::{DateTime, Number, Utc};
6use chrono::NaiveDate;
7use serde::{Deserialize, Serialize};
8
9pub mod formulas;
10
11#[cfg(test)]
12mod tests;
13
14#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone, Hash)]
16#[serde(rename_all = "snake_case")]
17pub enum NumberFormat {
18 Number,
19 NumberWithCommas,
20 Percent,
21 Dollar,
22 Euro,
23 Pound,
24 Yen,
25 Ruble,
26 Rupee,
27 Won,
28 Yuan,
29}
30
31#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone)]
32pub struct NumberDetails {
33 pub format: NumberFormat,
34}
35
36#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone)]
37#[serde(transparent)]
38pub struct SelectOptionId(String);
39
40#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone)]
41#[serde(rename_all = "lowercase")]
42pub enum Color {
43 Default,
44 Gray,
45 Brown,
46 Orange,
47 Yellow,
48 Green,
49 Blue,
50 Purple,
51 Pink,
52 Red,
53}
54
55#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
56pub struct SelectOption {
57 pub name: String,
58 pub id: SelectOptionId,
59 pub color: Color,
60}
61
62#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
63pub struct Select {
64 pub options: Vec<SelectOption>,
66}
67
68#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
69pub struct StatusGroupOption {
70 pub name: String,
71 pub id: SelectOptionId,
72 pub color: Color,
73 pub option_ids: Vec<SelectOptionId>,
74}
75
76#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
77pub struct Status {
78 pub options: Vec<SelectOption>,
80 pub groups: Vec<StatusGroupOption>,
82}
83
84#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
85pub struct Formula {
86 pub expression: String,
88}
89
90#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
91pub struct Relation {
92 pub database_id: DatabaseId,
95 pub synced_property_name: Option<String>,
99 pub synced_property_id: Option<PropertyId>,
104}
105
106#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Copy, Clone)]
109#[serde(rename_all = "snake_case")]
110pub enum RollupFunction {
111 Average,
112 Checked,
113 Count,
114 CountPerGroup,
115 CountValues,
116 DateRange,
117 EarliestDate,
118 Empty,
119 LatestDate,
120 Max,
121 Median,
122 Min,
123 NotEmpty,
124 PercentChecked,
125 PercentEmpty,
126 PercentNotEmpty,
127 PercentPerGroup,
128 PercentUnchecked,
129 Range,
130 ShowOriginal,
131 ShowUnique,
132 Sum,
133 Unchecked,
134 Unique,
135}
136
137#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
138pub struct Rollup {
139 pub relation_property_name: String,
141 pub relation_property_id: PropertyId,
143 pub rollup_property_name: String,
146 pub rollup_property_id: String,
149 pub function: RollupFunction,
151}
152
153#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
154#[serde(tag = "type")]
155#[serde(rename_all = "snake_case")]
156pub enum PropertyConfiguration {
157 Title { id: PropertyId },
160 #[serde(rename = "rich_text")]
163 Text { id: PropertyId },
164 Number {
167 id: PropertyId,
168 number: NumberDetails,
170 },
171 Select { id: PropertyId, select: Select },
174 Status { id: PropertyId, status: Status },
176 MultiSelect {
179 id: PropertyId,
180 multi_select: Select,
181 },
182 Date { id: PropertyId },
185 People { id: PropertyId },
188 Files { id: PropertyId },
193 Checkbox { id: PropertyId },
196 Url { id: PropertyId },
199 Email { id: PropertyId },
202 PhoneNumber { id: PropertyId },
205 Formula { id: PropertyId, formula: Formula },
207 Relation { id: PropertyId, relation: Relation },
209 Rollup { id: PropertyId, rollup: Rollup },
211 CreatedTime { id: PropertyId },
213 CreatedBy { id: PropertyId },
215 LastEditedTime { id: PropertyId },
217 LastEditBy { id: PropertyId },
219}
220
221#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
222pub struct SelectedValue {
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub id: Option<SelectOptionId>,
225 #[serde(skip_serializing_if = "Option::is_none")]
226 pub name: Option<String>,
227 pub color: Color,
228}
229
230#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
231#[serde(untagged)]
232pub enum DateOrDateTime {
233 Date(NaiveDate),
234 DateTime(DateTime<Utc>),
235}
236
237#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
238pub struct DateValue {
239 pub start: DateOrDateTime,
240 pub end: Option<DateOrDateTime>,
241 pub time_zone: Option<String>,
242}
243
244#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
247#[serde(tag = "type")]
248#[serde(rename_all = "snake_case")]
249pub enum FormulaResultValue {
250 String { string: Option<String> },
251 Number { number: Option<Number> },
252 Boolean { boolean: Option<bool> },
253 Date { date: Option<DateValue> },
254}
255
256#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
260pub struct RelationValue {
261 pub id: PageId,
262}
263
264#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
265#[serde(tag = "type", rename_all = "snake_case")]
266pub enum RollupValue {
267 Number { number: Option<Number> },
268 Date { date: Option<DateTime<Utc>> },
269 Array { array: Vec<RollupPropertyValue> },
270}
271
272#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
273pub struct FileReference {
274 pub name: String,
275 pub url: String,
276 pub mime_type: String,
277}
278
279#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
280#[serde(tag = "type")]
281#[serde(rename_all = "snake_case")]
282pub enum PropertyValue {
283 Title {
285 id: PropertyId,
286 title: Vec<RichText>,
287 },
288 #[serde(rename = "rich_text")]
290 Text {
291 id: PropertyId,
292 rich_text: Vec<RichText>,
293 },
294 Number {
296 id: PropertyId,
297 number: Option<Number>,
298 },
299 Select {
301 id: PropertyId,
302 select: Option<SelectedValue>,
303 },
304 Status {
306 id: PropertyId,
307 status: Option<SelectedValue>,
308 },
309 MultiSelect {
311 id: PropertyId,
312 multi_select: Option<Vec<SelectedValue>>,
313 },
314 Date {
316 id: PropertyId,
317 date: Option<DateValue>,
318 },
319 Formula {
321 id: PropertyId,
322 formula: FormulaResultValue,
323 },
324 Relation {
327 id: PropertyId,
328 relation: Option<Vec<RelationValue>>,
329 },
330 Rollup {
332 id: PropertyId,
333 rollup: Option<RollupValue>,
334 },
335 People { id: PropertyId, people: Vec<User> },
337 Files {
339 id: PropertyId,
340 files: Option<Vec<FileReference>>,
341 },
342 Checkbox { id: PropertyId, checkbox: bool },
344 Url { id: PropertyId, url: Option<String> },
346 Email {
348 id: PropertyId,
349 email: Option<String>,
350 },
351 PhoneNumber {
353 id: PropertyId,
354 phone_number: String,
355 },
356 CreatedTime {
358 id: PropertyId,
359 created_time: DateTime<Utc>,
360 },
361 CreatedBy { id: PropertyId, created_by: User },
363 LastEditedTime {
365 id: PropertyId,
366 last_edited_time: DateTime<Utc>,
367 },
368 LastEditedBy {
370 id: PropertyId,
371 last_edited_by: User,
372 },
373}
374
375#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
377#[serde(tag = "type")]
378#[serde(rename_all = "snake_case")]
379pub enum RollupPropertyValue {
380 #[serde(rename = "rich_text")]
382 Text {
383 rich_text: Vec<RichText>,
384 },
385 Number {
387 number: Option<Number>,
388 },
389 Select {
391 select: Option<SelectedValue>,
392 },
393 Status {
394 status: Option<SelectedValue>,
395 },
396 MultiSelect {
397 multi_select: Option<Vec<SelectedValue>>,
398 },
399 Date {
400 date: Option<DateValue>,
401 },
402 Formula {
404 formula: FormulaResultValue,
405 },
406 Relation {
409 relation: Option<Vec<RelationValue>>,
410 },
411 Rollup {
413 rollup: Option<RollupValue>,
414 },
415 People {
416 people: Vec<User>,
417 },
418 Files {
419 files: Option<Vec<FileReference>>,
420 },
421 Checkbox {
422 checkbox: bool,
423 },
424 Url {
425 url: Option<String>,
426 },
427 Email {
428 email: Option<String>,
429 },
430 PhoneNumber {
431 phone_number: String,
432 },
433 CreatedTime {
434 created_time: DateTime<Utc>,
435 },
436 CreatedBy {
437 created_by: User,
438 },
439 LastEditedTime {
440 last_edited_time: DateTime<Utc>,
441 },
442 LastEditedBy {
443 last_edited_by: User,
444 },
445}