shared/domain/
circle.rs

1//! Types for Circles.
2
3use chrono::{DateTime, Utc};
4use macros::make_path_parts;
5use serde::{Deserialize, Serialize};
6
7use crate::api::endpoints::PathPart;
8use strum_macros::Display;
9
10use super::{asset::UserOrMe, image::ImageId, user::UserId};
11
12wrap_uuid! {
13    /// Wrapper type around [`Uuid`], represents the ID of a Circle.
14    #[serde(rename_all = "camelCase")]
15    pub struct CircleId
16}
17
18/// The response returned when a request for `GET`ing a Circle is successful.
19#[derive(Serialize, Deserialize, Debug, Clone)]
20#[serde(rename_all = "camelCase")]
21pub struct Circle {
22    /// The ID of the Circle.
23    pub id: CircleId,
24
25    /// The Circle's name.
26    pub display_name: String,
27
28    /// Creator of Circle
29    pub created_by: UserId,
30
31    /// Description of the Circle. Defaults to empty string.
32    pub description: String,
33
34    /// Number of members on Circle
35    pub member_count: u32,
36
37    /// Image of Circle
38    pub image: ImageId,
39
40    /// When Circle was created
41    pub created_at: DateTime<Utc>,
42
43    /// When Circle was last edited
44    pub last_edited: Option<DateTime<Utc>>,
45
46    /// Current user is member of circle
47    pub joined: bool,
48}
49
50make_path_parts!(CircleCreatePath => "/v1/circle");
51
52/// Request to create a new Circle.
53///
54/// This creates the draft and live [Circle Data](Circle Data) copies with the requested info.
55#[derive(Serialize, Deserialize, Debug)]
56#[serde(rename_all = "camelCase")]
57pub struct CircleCreateRequest {
58    /// The Circle's name.
59    pub display_name: String,
60
61    /// Description of the Circle. Defaults to empty string.
62    pub description: String,
63
64    /// Image of the Circle
65    pub image: ImageId,
66}
67
68make_path_parts!(UpdateCirclePath => "/v1/circle/{}" => CircleId);
69
70/// Request for updating a Circle's draft data.
71#[derive(Serialize, Deserialize, Debug, Default)]
72#[serde(rename_all = "camelCase")]
73pub struct CircleUpdateRequest {
74    /// The Circle's name to be updated.
75    #[serde(skip_serializing_if = "Option::is_none")]
76    #[serde(default)]
77    pub display_name: Option<String>,
78
79    /// Description of the Circle to be updated.
80    #[serde(skip_serializing_if = "Option::is_none")]
81    #[serde(default)]
82    pub description: Option<String>,
83
84    /// image of the Circle to be updated.
85    #[serde(skip_serializing_if = "Option::is_none")]
86    #[serde(default)]
87    pub image: Option<ImageId>,
88}
89
90make_path_parts!(CircleBrowsePath => "/v1/circle/browse");
91
92/// Query for [`Browse`](crate::api::endpoints::circle::Browse).
93#[derive(Serialize, Deserialize, Clone, Debug, Default)]
94#[serde(rename_all = "camelCase")]
95pub struct CircleBrowseQuery {
96    /// creator of circles
97    #[serde(default)]
98    #[serde(skip_serializing_if = "Option::is_none")]
99    pub creator_id: Option<UserOrMe>,
100
101    /// creator of circles
102    /// The hits per page to be returned
103    #[serde(default)]
104    #[serde(serialize_with = "super::csv_encode_uuids")]
105    #[serde(deserialize_with = "super::from_csv")]
106    #[serde(skip_serializing_if = "Vec::is_empty")]
107    pub users: Vec<UserId>,
108
109    /// The page number to get.
110    #[serde(default)]
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub page: Option<u32>,
113
114    /// The hits per page to be returned
115    #[serde(default)]
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub page_limit: Option<u32>,
118
119    /// Order by sort
120    #[serde(default)]
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub order_by: Option<OrderBy>,
123}
124
125/// Response for [`Browse`](crate::api::endpoints::circle::Browse).
126#[derive(Serialize, Deserialize, Clone, Debug)]
127#[serde(rename_all = "camelCase")]
128pub struct CircleBrowseResponse {
129    /// the Circles returned.
130    pub circles: Vec<Circle>,
131
132    /// The number of pages found.
133    pub pages: u32,
134
135    /// The total number of Circles found
136    pub total_circle_count: u64,
137}
138
139make_path_parts!(CircleSearchPath => "/v1/circle");
140
141/// Search for Circles via the given query string.
142#[derive(Serialize, Deserialize, Clone, Debug, Default)]
143#[serde(rename_all = "camelCase")]
144pub struct CircleSearchQuery {
145    /// The query string.
146    #[serde(default)]
147    #[serde(skip_serializing_if = "String::is_empty")]
148    pub q: String,
149
150    /// The page number of the Circles to get.
151    #[serde(default)]
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub page: Option<u32>,
154
155    /// Optionally filter by author's id
156    #[serde(default)]
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub creator_id: Option<UserOrMe>,
159
160    /// Optionally filter by the author's name
161    #[serde(default)]
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub creator_name: Option<String>,
164
165    /// The hits per page to be returned
166    #[serde(default)]
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub page_limit: Option<u32>,
169}
170
171/// Response for [`Search`](crate::api::endpoints::circle::Search).
172#[derive(Serialize, Deserialize, Clone, Debug)]
173#[serde(rename_all = "camelCase")]
174pub struct CircleSearchResponse {
175    /// the Circles returned.
176    pub circles: Vec<Circle>,
177
178    /// The number of pages found.
179    pub pages: u32,
180
181    /// The total number of Circles found
182    pub total_circle_count: u64,
183}
184
185make_path_parts!(CircleDeletePath => "/v1/circle/{}" => CircleId);
186
187make_path_parts!(CircleGetPath => "/v1/circle/{}" => CircleId);
188
189make_path_parts!(JoinCirclePath => "/v1/circle/{}/join" => CircleId);
190
191make_path_parts!(LeaveCirclePath => "/v1/circle/{}/leave" => CircleId);
192
193make_path_parts!(CircleRemoveMemberPath => "/v1/circle/{}/members/{}" => CircleId, UserId);
194
195make_path_parts!(CircleBrowseMembersPath => "/v1/circle/{}/members" => CircleId);
196
197/// Browse for Circles
198#[derive(Serialize, Deserialize, Clone, Debug, Default)]
199#[serde(rename_all = "camelCase")]
200pub struct BrowseMembersQuery {
201    /// filter members by scope
202    #[serde(default)]
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub admin: Option<bool>,
205}
206
207/// Members associated with Circle
208#[derive(Serialize, Deserialize)]
209pub struct BrowseMembersResponse {
210    /// user id of member
211    pub members: Vec<UserId>,
212
213    /// user id of member
214    pub count: u32,
215}
216
217/// Sort browse results
218#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Debug, Display)]
219#[cfg_attr(feature = "backend", derive(sqlx::Type))]
220#[serde(rename_all = "camelCase")]
221#[repr(i16)]
222pub enum OrderBy {
223    /// Order Circles by member count
224    #[strum(serialize = "MemberCount")]
225    MemberCount = 0,
226}