feat(export): add issues issue export
zhenyi committed
Added lib/export/issues/issue.rs lib/export/issues/issue.rs +97 −0 View lib/export/issues/issue.rs
@@ -0,0 +1,97 @@
1use db::issue::issue as issue_entity;
2use serde::{Deserialize, Serialize};
3use time::OffsetDateTime;
4use time::format_description::well_known::Rfc3339;
5use utoipa::{IntoParams, ToSchema};
6use uuid::Uuid;
7
8fn fmt_ts(ts: OffsetDateTime) -> String {
9 ts.format(&Rfc3339).unwrap_or_default()
10}
11fn fmt_ts_opt(ts: Option<OffsetDateTime>) -> Option<String> {
12 ts.map(fmt_ts)
13}
14
15#[derive(Debug, Clone, Copy, Serialize, Deserialize, ToSchema, PartialEq, Eq)]
16#[serde(rename_all = "snake_case")]
17pub enum IssueState {
18 Open,
19 Closed,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
23pub struct IssueView {
24 pub id: Uuid,
25 pub collection_id: Uuid,
26 pub autoincrement_id: i32,
27 pub author_id: Uuid,
28 pub title: String,
29 pub description: Option<String>,
30 pub body: String,
31 pub milestone_id: Option<Uuid>,
32 pub state: IssueState,
33 pub created_at: String,
34 pub updated_at: Option<String>,
35 pub closed_at: Option<String>,
36}
37
38impl From<issue_entity::Model> for IssueView {
39 fn from(m: issue_entity::Model) -> Self {
40 let state = if m.closed_at.is_some() {
41 IssueState::Closed
42 } else {
43 IssueState::Open
44 };
45 Self {
46 id: m.id,
47 collection_id: m.collection_id,
48 autoincrement_id: m.autoincrement_id,
49 author_id: m.author_id,
50 title: m.title,
51 description: m.description,
52 body: m.body,
53 milestone_id: m.milestone_id,
54 state,
55 created_at: fmt_ts(m.created_at),
56 updated_at: fmt_ts_opt(m.updated_at),
57 closed_at: fmt_ts_opt(m.closed_at),
58 }
59 }
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
63pub struct IssuePage {
64 pub items: Vec<IssueView>,
65 pub total: i64,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
69pub struct CreateIssueOption {
70 pub title: String,
71 pub description: Option<String>,
72 pub body: String,
73 pub milestone_id: Option<Uuid>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
77pub struct UpdateIssueOption {
78 pub title: Option<String>,
79 pub description: Option<Option<String>>,
80 pub body: Option<String>,
81 pub milestone_id: Option<Option<Uuid>>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
85pub struct CloseIssueOption {
86 pub closed: bool,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, IntoParams)]
90pub struct ListIssueQuery {
91 pub state: Option<IssueState>,
92 pub author_id: Option<Uuid>,
93 pub milestone_id: Option<Uuid>,
94 pub q: Option<String>,
95 pub limit: Option<u64>,
96 pub offset: Option<u64>,
97}
No newline at end of file