1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use serde::{Deserialize, Serialize};

use crate::i18n::I18n;
use crate::image::Image;
use crate::pagination::Page;
use crate::params;
use crate::tag::Tag;

// Project is a search resource.
#[derive(Debug, Serialize, Deserialize)]
pub struct Project {
    // Link to the project page on the Ulule website
    pub absolute_url: String,
    // Amount raised in project currency
    pub amount_raised: u64,
    // Two-letter ISO code of the country
    pub country: String,
    // Two-letter ISO code of the currency
    pub currency: String,
    // Date at which the funding campaign ends, with RFC 3339 format
    pub date_end: Option<String>,
    // Date at which the funding campaign starts, with RFC 3339 format
    pub date_start: Option<String>,
    // True if the funding campaign is finished
    pub finished: bool,
    // Goal in the project currency if type is project, or number of pre-orders if type is presale.
    pub goal: u64,
    // Unique id of the project
    pub id: u64,
    // Main language of the project
    pub lang: String,
    // Name of the project
    pub name: I18n,
    // Number of products sold
    pub nb_products_sold: u64,
    // Unique slug of the project
    pub slug: String,
    // Subtitle of the project
    pub subtitle: I18n,
    // Type of the project (presale or project)
    #[serde(alias = "type")]
    pub kind: String,

    // The following fields are extra_fields and must be explicitly specified in the request:
    // Main image of the project
    pub main_image: Option<Image>,
    // Main tag of the project
    pub main_tag: Option<Tag>,
    // Owner is the project owner
    pub owner: Option<User>,
}

// Projects is a paginated list of search project resource.
#[derive(Debug, Serialize, Deserialize)]
pub struct Projects {
    pub projects: Vec<Project>,
    pub meta: Page,
}

// User is the user resource.
#[derive(Debug, Serialize, Deserialize)]
pub struct User {
    // Link to the profile page on the Ulule website
    pub absolute_url: String,
    // First name of the user
    pub first_name: String,
    // Unique id of the user
    pub id: u64,
    // Last name of the user
    pub last_name: String,
    // Concatenation of first name and last name if they exist, username otherwise
    pub name: String,
    // Unique screenname of the user
    pub screenname: String,
    // Unique username of the user
    pub username: String,
}

pub type Params = params::Params;

impl Params {
    // Filter projects by language
    pub fn with_langs(self, langs: Vec<String>) -> Params {
        self.add_query("langs", langs.join(","))
    }
    // Filter projects by country
    pub fn with_countries(self, countries: Vec<String>) -> Params {
        self.add_query("countries", countries.join(","))
    }
    // Filter projects by partner
    pub fn with_partners(self, partners: Vec<String>) -> Params {
        self.add_query("partners", partners.join(","))
    }
    // Filter projects by status
    pub fn with_status(self, status: impl Into<String>) -> Params {
        self.add_query("status", status)
    }
    // Filter projects by ids
    pub fn with_selected_ids(self, ids: Vec<u64>) -> Params {
        let selected: Vec<String> = ids.iter().map(|i| i.to_string()).collect();
        self.add_query("selected_ids", selected.join(","))
    }
    // Filter projects with description, name or subtitle matching the given term
    pub fn with_term(self, term: impl Into<String>) -> Params {
        self.add_query(term, "")
    }
    // Sort field, can be one of popular, amount, ending-soon or new
    // default is popular
    pub fn with_query_sort(self, sort: String) -> Params {
        self.add_query("sort", sort)
    }
    // Filter projects by tag
    pub fn with_tag_id(self, id: u64) -> Params {
        self.add_query("tag_id", id.to_string())
    }
    // Filter projects by owner
    pub fn with_owner_id(self, id: u64) -> Params {
        self.add_query("owner_id", id.to_string())
    }
    // Filter projects by city
    pub fn with_city_id(self, id: u64) -> Params {
        self.add_query("city_id", id.to_string())
    }
    // Filter projects by region
    pub fn with_region_id(self, id: u64) -> Params {
        self.add_query("region_id", id.to_string())
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn with_selected_ids() {
        use super::Params;
        let p = Params::new().with_selected_ids(vec![42, 1337]);
        assert_eq!(p.to_string(), "?q=selected_ids:42,1337");
    }
}