hubcaps_ex/
milestone.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use url::form_urlencoded;
5
6use crate::{Future, Github, SortDirection, Stream};
7use crate::issues::State;
8use crate::users::User;
9
10pub struct Milestones {
11    github: Github,
12    owner: String,
13    repo: String,
14}
15
16#[derive(Debug, Serialize, Deserialize)]
17pub struct Milestone {
18    pub url: String,
19    pub html_url: String,
20    pub labels_url: String,
21    pub id: u64,
22    pub node_id: String,
23    pub number: u64,
24    pub title: String,
25    pub description: Option<String>,
26    pub creator: User,
27    pub open_issues: u64,
28    pub closed_issues: u64,
29    pub state: String,
30    pub created_at: String,
31    pub updated_at: String,
32    pub due_on: Option<String>,
33    pub closed_at: Option<String>,
34}
35
36#[derive(Debug, Serialize)]
37pub struct MilestoneOptions {
38    pub title: String,
39    pub state: String,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub description: Option<String>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub due_on: Option<String>,
44}
45
46#[derive(Default)]
47pub struct MilestoneListOptions {
48    params: HashMap<&'static str, String>,
49}
50
51impl MilestoneListOptions {
52    pub fn builder() -> MilestoneListOptionsBuilder {
53        MilestoneListOptionsBuilder::default()
54    }
55
56    pub fn serialize(&self) -> Option<String> {
57        if self.params.is_empty() {
58            None
59        } else {
60            let encoded: String = form_urlencoded::Serializer::new(String::new())
61                .extend_pairs(&self.params)
62                .finish();
63            Some(encoded)
64        }
65    }
66}
67
68/// a mutable issue list builder
69#[derive(Default)]
70pub struct MilestoneListOptionsBuilder(MilestoneListOptions);
71
72impl MilestoneListOptionsBuilder {
73    pub fn state(&mut self, state: State) -> &mut Self {
74        self.0.params.insert("state", state.to_string());
75        self
76    }
77
78    pub fn direction(&mut self, direction: SortDirection) -> &mut Self {
79        self.0.params.insert("direction", direction.to_string());
80        self
81    }
82
83    pub fn per_page(&mut self, n: u32) -> &mut Self {
84        self.0.params.insert("per_page", n.to_string());
85        self
86    }
87
88    pub fn build(&self) -> MilestoneListOptions {
89        MilestoneListOptions {
90            params: self.0.params.clone(),
91        }
92    }
93}
94
95impl Milestones {
96    /// create a new instance of a github repo issue ref
97    pub fn new<O, R>(github: Github, owner: O, repo: R) -> Self
98        where
99            O: Into<String>,
100            R: Into<String>,
101    {
102        Milestones {
103            github,
104            owner: owner.into(),
105            repo: repo.into(),
106        }
107    }
108
109    fn path(&self, more: &str) -> String {
110        format!("/repos/{}/{}/milestones{}", self.owner, self.repo, more)
111    }
112
113    pub fn create(&self, is: &MilestoneOptions) -> Future<Milestone> {
114        self.github.post(&self.path(""), json!(is))
115    }
116
117    pub fn update(&self, is: &MilestoneOptions) -> Future<Milestone> {
118        self.github.patch(&self.path(""), json!(is))
119    }
120
121    /// Return the first page of issues for this repisotiry
122    /// See the [github docs](https://developer.github.com/v3/issues/#list-issues-for-a-repository)
123    /// for more information
124    pub fn list(&self, options: &MilestoneListOptions) -> Future<Vec<Milestone>> {
125        let mut uri = vec![self.path("")];
126        if let Some(query) = options.serialize() {
127            uri.push(query);
128        }
129        self.github.get(&uri.join("?"))
130    }
131
132    /// Return a stream of all issues for this repository
133    ///
134    /// See the [github docs](https://developer.github.com/v3/issues/#list-issues-for-a-repository)
135    /// for more information
136    ///
137    /// Note: You'll typically want to use a `IssueListOptions` with a `per_page`
138    /// of 100 for maximum api credential rate limit efficency
139    pub fn iter(&self, options: &MilestoneListOptions) -> Stream<Milestone> {
140        let mut uri = vec![self.path("")];
141        if let Some(query) = options.serialize() {
142            uri.push(query);
143        }
144        self.github.get_stream(&uri.join("?"))
145    }
146}