1use actix_web::web::Query;
4use actix_web::{
5 delete, get, patch, post,
6 web::{Json, Path},
7 HttpResponse, Result,
8};
9use uuid::Uuid;
10
11use crate::{
12 config::{
13 auth::user_info::UserInfo,
14 data::{SharedBroadcaster, SharedPool},
15 },
16 model::dto::{
17 actions::{Action, ActionType, UpdateMapGeometryActionPayload},
18 MapSearchParameters, NewMapDto, PageParameters, UpdateMapDto, UpdateMapGeometryDto,
19 },
20 service,
21};
22
23#[utoipa::path(
30 context_path = "/api/maps",
31 params(
32 MapSearchParameters,
33 PageParameters
34 ),
35 responses(
36 (status = 200, description = "Fetch or search all maps", body = PageMapDto)
37 ),
38 security(
39 ("oauth2" = [])
40 )
41)]
42#[get("")]
43pub async fn find(
44 search_query: Query<MapSearchParameters>,
45 page_query: Query<PageParameters>,
46 pool: SharedPool,
47) -> Result<HttpResponse> {
48 let response =
49 service::map::find(search_query.into_inner(), page_query.into_inner(), &pool).await?;
50 Ok(HttpResponse::Ok().json(response))
51}
52
53#[utoipa::path(
58 context_path = "/api/maps",
59 responses(
60 (status = 200, description = "Fetch a map by id", body = MapDto)
61 ),
62 security(
63 ("oauth2" = [])
64 )
65)]
66#[get("/{map_id}")]
67pub async fn find_by_id(map_id: Path<i32>, pool: SharedPool) -> Result<HttpResponse> {
68 let response = service::map::find_by_id(*map_id, &pool).await?;
69 Ok(HttpResponse::Ok().json(response))
70}
71
72#[utoipa::path(
77 context_path = "/api/maps",
78 request_body = NewMapDto,
79 responses(
80 (status = 201, description = "Create a new map", body = MapDto)
81 ),
82 security(
83 ("oauth2" = [])
84 )
85)]
86#[post("")]
87pub async fn create(
88 new_map_json: Json<NewMapDto>,
89 user_info: UserInfo,
90 pool: SharedPool,
91) -> Result<HttpResponse> {
92 let response = service::map::create(new_map_json.0, user_info.id, &pool).await?;
93 Ok(HttpResponse::Created().json(response))
94}
95
96#[utoipa::path(
101 context_path = "/api/maps",
102 request_body = UpdateMapDto,
103 responses(
104 (status = 200, description = "Update a map", body = MapDto)
105 ),
106 security(
107 ("oauth2" = [])
108 )
109)]
110#[patch("/{map_id}")]
111pub async fn update(
112 map_update_json: Json<UpdateMapDto>,
113 map_id: Path<i32>,
114 user_info: UserInfo,
115 pool: SharedPool,
116) -> Result<HttpResponse> {
117 let response =
118 service::map::update(map_update_json.0, map_id.into_inner(), user_info.id, &pool).await?;
119 Ok(HttpResponse::Ok().json(response))
120}
121#[utoipa::path(
126context_path = "/api/maps",
127request_body = UpdateMapDto,
128responses(
129(status = 200, description = "Update a map", body = MapDto)
130),
131security(
132("oauth2" = [])
133)
134)]
135#[patch("/{map_id}/geometry")]
136pub async fn update_geometry(
137 map_update_geometry_json: Json<UpdateMapGeometryDto>,
138 map_id: Path<i32>,
139 user_info: UserInfo,
140 pool: SharedPool,
141 broadcaster: SharedBroadcaster,
142) -> Result<HttpResponse> {
143 let map_id_inner = map_id.into_inner();
144
145 let response = service::map::update_geometry(
146 map_update_geometry_json.0.clone(),
147 map_id_inner,
148 user_info.id,
149 &pool,
150 )
151 .await?;
152
153 broadcaster
154 .broadcast(
155 map_id_inner,
156 Action {
157 action_id: Uuid::new_v4(),
158 user_id: user_info.id,
159 action: ActionType::UpdateMapGeometry(UpdateMapGeometryActionPayload::new(
160 map_update_geometry_json.0,
161 map_id_inner,
162 )),
163 },
164 )
165 .await;
166
167 Ok(HttpResponse::Ok().json(response))
168}
169
170#[utoipa::path(
175 context_path = "/api/maps",
176 responses(
177 (status = 200, description = "Delete a map by id")
178 ),
179 security(
180 ("oauth2" = [])
181 )
182)]
183#[delete("/{map_id}")]
184pub async fn delete_by_id(
185 map_id: Path<i32>,
186 user_info: UserInfo,
187 pool: SharedPool,
188) -> Result<HttpResponse> {
189 service::map::delete_by_id(*map_id, user_info.id, &pool).await?;
190 Ok(HttpResponse::Ok().finish())
191}