1use ofdb_boundary::*;
2use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
3use seed::browser::fetch::{fetch, Header, Method, Request, Result};
4
5#[derive(Debug, Clone)]
7pub struct Api {
8 url: String,
9}
10
11impl Api {
12 pub fn new(url: String) -> Self {
13 Self { url }
14 }
15 pub async fn search(&self, txt: &str, bbox: &MapBbox) -> Result<SearchResponse> {
16 let encoded_txt = utf8_percent_encode(txt, NON_ALPHANUMERIC);
17 let MapBbox { sw, ne } = bbox;
18 let bbox_str = format!("{},{},{},{}", sw.lat, sw.lng, ne.lat, ne.lng);
19 let url = format!("{}/search?text={}&bbox={}", self.url, encoded_txt, bbox_str);
20 let response = fetch(url).await?;
21 response
22 .check_status()? .json()
24 .await
25 }
26 pub async fn places(&self, ids: &[String]) -> Result<Vec<Entry>> {
27 let ids = ids.join(",");
28 let url = format!("{}/entries/{}", self.url, ids);
29 let response = fetch(url).await?;
30 response
31 .check_status()? .json()
33 .await
34 }
35 pub async fn create_place(&self, place: &NewPlace) -> Result<()> {
36 let url = format!("{}/entries", self.url);
37 let request = Request::new(url).method(Method::Post).json(place)?;
38 let response = fetch(request).await?;
39 response.check_status()?; Ok(())
41 }
42 pub async fn update_place(&self, id: &str, place: &UpdatePlace) -> Result<()> {
43 let url = format!("{}/entries/{}", self.url, id);
44 let request = Request::new(url).method(Method::Put).json(place)?;
45 let response = fetch(request).await?;
46 response.check_status()?; Ok(())
48 }
49 pub async fn get_places_clearance_with_api_token(
50 &self,
51 api_token: &str,
52 ) -> Result<Vec<PendingClearanceForPlace>> {
53 let url = format!("{}/places/clearance", self.url);
54 let request = Request::new(url)
55 .method(Method::Get)
56 .header(Header::bearer(api_token));
57 let response = fetch(request).await?;
58 let result = response.check_status()?.json().await?;
59 Ok(result)
60 }
61 pub async fn get_place_history_with_api_token(
62 &self,
63 api_token: &str,
64 id: &str,
65 ) -> Result<PlaceHistory> {
66 let url = format!("{}/places/{}/history", self.url, id);
67 let request = Request::new(url)
68 .method(Method::Get)
69 .header(Header::bearer(api_token));
70 let response = fetch(request).await?;
71 let result = response
72 .check_status()? .json()
74 .await?;
75 Ok(result)
76 }
77 pub async fn post_places_clearance_with_api_token(
78 &self,
79 api_token: &str,
80 clearances: Vec<ClearanceForPlace>,
81 ) -> Result<ResultCount> {
82 let url = format!("{}/places/clearance", self.url);
83 let request = Request::new(url)
84 .method(Method::Post)
85 .header(Header::bearer(api_token))
86 .json(&clearances)?;
87 let response = fetch(request).await?;
88 let result = response
89 .check_status()? .json()
91 .await?;
92 Ok(result)
93 }
94 pub async fn post_login(&self, req: &Credentials) -> Result<()> {
95 let url = format!("{}/login", self.url);
96 let request = Request::new(url)
97 .credentials(web_sys::RequestCredentials::Include)
98 .method(Method::Post)
99 .json(&req)?;
100 let response = fetch(request).await?;
101 response.check_status()?; Ok(())
103 }
104 pub async fn post_logout(&self) -> Result<()> {
105 let url = format!("{}/logout", self.url);
106 let request = Request::new(url)
107 .method(Method::Post)
108 .credentials(web_sys::RequestCredentials::Include)
109 .json(&())?;
110 let response = fetch(request).await?;
111 response.check_status()?; Ok(())
113 }
114 pub async fn get_users_current(&self) -> Result<User> {
115 let url = format!("{}/users/current", self.url);
116 let request = Request::new(url)
117 .method(Method::Get)
118 .credentials(web_sys::RequestCredentials::Include);
119 let response = fetch(request).await?;
120 let result = response
121 .check_status()? .json()
123 .await?;
124 Ok(result)
125 }
126 pub async fn get_tags(&self) -> Result<Vec<String>> {
127 let url = format!("{}/tags", self.url);
128 let request = Request::new(url).method(Method::Get);
129 let response = fetch(request).await?;
130 let result = response
131 .check_status()? .json()
133 .await?;
134 Ok(result)
135 }
136 pub async fn get_most_popular_tags(
137 &self,
138 min_count: Option<usize>,
139 max_count: Option<usize>,
140 limit: Option<usize>,
141 offset: Option<usize>,
142 ) -> Result<Vec<TagFrequency>> {
143 let mut url = format!("{}/entries/most-popular-tags", self.url);
144 if min_count.or(max_count).or(limit).or(offset).is_some() {
145 url = format!("{}?", url);
146 if let Some(cnt) = min_count {
147 url = format!("{}&min_count={}", url, cnt);
148 }
149 if let Some(cnt) = max_count {
150 url = format!("{}&max_count={}", url, cnt);
151 }
152 if let Some(l) = limit {
153 url = format!("{}&limit={}", url, l);
154 }
155 if let Some(o) = offset {
156 url = format!("{}&offset={}", url, o);
157 }
158 }
159 let request = Request::new(url).method(Method::Get);
160 let response = fetch(request).await?;
161 let result = response
162 .check_status()? .json()
164 .await?;
165 Ok(result)
166 }
167}