1use std::collections::BTreeMap;
4
5use crate::api::endpoints::PathPart;
6use macros::make_path_parts;
7use serde::{Deserialize, Serialize};
8use uuid::Uuid;
9
10#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
12#[serde(rename_all = "camelCase")]
13pub struct Bundle {
14 pub id: Uuid,
16
17 pub name: String,
19}
20
21#[derive(Serialize, Deserialize, Clone, Debug)]
23#[serde(rename_all = "camelCase")]
24pub struct ItemKind {
25 pub id: Uuid,
27
28 pub name: String,
30}
31
32#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
34#[serde(rename_all = "camelCase")]
35#[cfg_attr(feature = "backend", derive(sqlx::Type))]
36#[repr(i16)]
37pub enum EntryStatus {
38 Approved = 0,
40
41 Discuss = 1,
43
44 OnHold = 2,
47}
48
49#[derive(Serialize, Deserialize, Clone, Debug)]
52#[serde(rename_all = "camelCase")]
53pub struct Entry {
54 pub id: u32,
56
57 pub bundle_id: Uuid,
59
60 pub section: Option<String>,
62
63 pub item_kind_id: Option<Uuid>,
65
66 pub english: Option<String>,
68
69 pub hebrew: Option<String>,
71
72 pub status: EntryStatus,
74
75 pub zeplin_reference: Option<String>,
77
78 pub comments: Option<String>,
80
81 pub in_app: bool,
83
84 pub in_element: bool,
86
87 pub in_mock: bool,
89}
90
91make_path_parts!(CreateEntryPath => "/v1/locale/entry");
92
93#[derive(Serialize, Deserialize, Clone, Debug)]
95#[serde(rename_all = "camelCase")]
96pub struct CreateEntryRequest {
97 pub bundle_id: Uuid,
99
100 pub section: Option<String>,
102
103 pub item_kind_id: Option<Uuid>,
105
106 pub english: Option<String>,
108
109 pub hebrew: Option<String>,
111
112 pub status: EntryStatus,
114
115 pub zeplin_reference: Option<String>,
117
118 pub comments: Option<String>,
120
121 pub in_app: bool,
123
124 pub in_element: bool,
126
127 pub in_mock: bool,
129}
130
131#[derive(Serialize, Deserialize, Clone, Debug)]
133#[serde(rename_all = "camelCase")]
134pub struct CreateEntryResponse {
135 pub id: u32,
137}
138
139#[derive(Serialize, Deserialize, Clone, Debug)]
141#[serde(rename_all = "camelCase")]
142#[non_exhaustive]
143pub enum ListEntryGroupBy {
144 None,
146
147 Bundle,
149}
150
151impl ListEntryGroupBy {
152 pub fn is_none(&self) -> bool {
154 matches!(self, Self::None)
155 }
156
157 pub fn is_bundle(&self) -> bool {
159 matches!(self, Self::Bundle)
160 }
161}
162
163impl Default for ListEntryGroupBy {
164 fn default() -> Self {
165 Self::None
166 }
167}
168
169make_path_parts!(ListEntryPath => "/v1/locale/entry");
170
171#[derive(Serialize, Deserialize, Clone, Debug, Default)]
173#[serde(rename_all = "camelCase")]
174pub struct ListEntryQuery {
175 #[serde(skip_serializing_if = "Vec::is_empty")]
177 #[serde(default)]
178 #[serde(
179 serialize_with = "crate::domain::csv_encode_uuids",
180 deserialize_with = "crate::domain::from_csv"
181 )]
182 pub bundles: Vec<Uuid>,
183
184 #[serde(skip_serializing_if = "ListEntryGroupBy::is_none")]
187 #[serde(default)]
188 pub group_by: ListEntryGroupBy,
189}
190
191#[derive(Serialize, Deserialize, Clone, Debug)]
193#[serde(rename_all = "camelCase")]
194pub enum ListEntryResponse {
195 Bundles(BTreeMap<Uuid, Vec<Entry>>),
197
198 List(Vec<Entry>),
200}
201
202make_path_parts!(GetEntryPath => "/v1/locale/entry/{}" => u32);
204
205#[derive(Serialize, Deserialize, Clone, Debug)]
207#[serde(rename_all = "camelCase")]
208pub struct GetEntryResponse {
209 pub entry: Entry,
211}
212
213make_path_parts!(UpdateEntryPath => "/v1/locale/entry/{}" => u32);
215
216#[derive(Serialize, Deserialize, Clone, Debug)]
218#[serde(rename_all = "camelCase")]
219pub struct UpdateEntryRequest {
220 #[serde(skip_serializing_if = "Option::is_none")]
222 #[serde(default)]
223 pub bundle_id: Option<Uuid>,
224
225 #[serde(deserialize_with = "super::deserialize_optional_field")]
227 #[serde(skip_serializing_if = "Option::is_none")]
228 #[serde(default)]
229 pub section: Option<Option<String>>,
230
231 #[serde(skip_serializing_if = "Option::is_none")]
233 #[serde(default)]
234 pub item_kind_id: Option<Uuid>,
235
236 #[serde(skip_serializing_if = "Option::is_none")]
238 #[serde(default)]
239 pub english: Option<String>,
240
241 #[serde(skip_serializing_if = "Option::is_none")]
243 #[serde(default)]
244 pub hebrew: Option<String>,
245
246 #[serde(skip_serializing_if = "Option::is_none")]
248 #[serde(default)]
249 pub status: Option<EntryStatus>,
250
251 #[serde(deserialize_with = "super::deserialize_optional_field")]
253 #[serde(skip_serializing_if = "Option::is_none")]
254 #[serde(default)]
255 pub zeplin_reference: Option<Option<String>>,
256
257 #[serde(deserialize_with = "super::deserialize_optional_field")]
259 #[serde(skip_serializing_if = "Option::is_none")]
260 #[serde(default)]
261 pub comments: Option<Option<String>>,
262
263 #[serde(skip_serializing_if = "Option::is_none")]
265 #[serde(default)]
266 pub in_app: Option<bool>,
267
268 #[serde(skip_serializing_if = "Option::is_none")]
270 #[serde(default)]
271 pub in_element: Option<bool>,
272
273 #[serde(skip_serializing_if = "Option::is_none")]
275 #[serde(default)]
276 pub in_mock: Option<bool>,
277}
278
279make_path_parts!(DeleteEntryPath => "/v1/locale/entry/{}" => u32);
281
282make_path_parts!(ListBundlePath => "/v1/locale/bundle");
283
284#[derive(Serialize, Deserialize, Clone, Debug)]
286#[serde(rename_all = "camelCase")]
287pub struct ListBundleResponse {
288 pub bundles: Vec<Bundle>,
290}
291
292make_path_parts!(ListItemKindPath => "/v1/locale/item-kind");
293
294#[derive(Serialize, Deserialize, Clone, Debug)]
296#[serde(rename_all = "camelCase")]
297pub struct ListItemKindResponse {
298 pub item_kinds: Vec<ItemKind>,
300}