1use actix_web::{
4 delete, get, post, put,
5 web::{Json, Path, Query},
6 HttpResponse, Result,
7};
8use uuid::Uuid;
9
10use crate::{
11 config::{
12 auth::user_info::UserInfo,
13 data::{SharedBroadcaster, SharedPool},
14 },
15 model::dto::{
16 actions::{Action, ActionType},
17 core::{
18 ActionDtoWrapper, ActionDtoWrapperDeleteLayer, ActionDtoWrapperNewLayer,
19 ActionDtoWrapperUpdateLayer,
20 },
21 layers::LayerSearchParameters,
22 },
23 service::layer,
24};
25
26#[utoipa::path(
32 context_path = "/api/maps/{map_id}/layers",
33 params(
34 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
35 LayerSearchParameters,
36 ),
37 responses(
38 (status = 200, description = "Search layers", body = VecLayerDto)
39 ),
40 security(
41 ("oauth2" = [])
42 )
43)]
44#[get("")]
45pub async fn find(
46 search_query: Query<LayerSearchParameters>,
47 map_id: Path<i32>,
48 pool: SharedPool,
49) -> Result<HttpResponse> {
50 let mut search_params = search_query.into_inner();
51 search_params.map_id = Some(map_id.into_inner());
52
53 let response = layer::find(search_params, &pool).await?;
54 Ok(HttpResponse::Ok().json(response))
55}
56
57#[utoipa::path(
62 context_path = "/api/maps/{map_id}/layers",
63 params(
64 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
65 ),
66 responses(
67 (status = 200, description = "Fetch layer by id", body = LayerDto)
68 ),
69 security(
70 ("oauth2" = [])
71 )
72)]
73#[get("/{id}")]
74pub async fn find_by_id(path: Path<(i32, Uuid)>, pool: SharedPool) -> Result<HttpResponse> {
75 let (_, id) = path.into_inner();
76 let response = layer::find_by_id(id, &pool).await?;
77 Ok(HttpResponse::Ok().json(response))
78}
79
80#[utoipa::path(
85 context_path = "/api/maps/{map_id}/layers",
86 params(
87 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
88 ),
89 request_body = ActionDtoWrapperUpdateLayer,
90 responses(
91 (status = 201, description = "Create a plant layer", body = LayerDto)
92 ),
93 security(
94 ("oauth2" = [])
95 )
96)]
97#[post("")]
98pub async fn create(
99 path: Path<i32>,
100 new_layer: Json<ActionDtoWrapperNewLayer>,
101 pool: SharedPool,
102 broadcaster: SharedBroadcaster,
103 user_info: UserInfo,
104) -> Result<HttpResponse> {
105 let ActionDtoWrapper { action_id, dto } = new_layer.into_inner();
106 let map_id = path.into_inner();
107 let user_id = user_info.id;
108
109 let dto = layer::create(map_id, dto, &pool).await?;
110
111 broadcaster
112 .broadcast(
113 map_id,
114 Action {
115 action_id,
116 user_id,
117 action: ActionType::CreateLayer(dto.clone()),
118 },
119 )
120 .await;
121
122 Ok(HttpResponse::Created().json(dto))
123}
124
125#[utoipa::path(
130 context_path = "/api/maps/{map_id}/layers",
131 params(
132 ("map_id" = i32, Path, description = "The id of the map"),
133 ),
134 request_body = ActionDtoWrapperUpdateLayer,
135 responses(
136 (status = 200, description = "Layers have been reordered")
137 ),
138 security(
139 ("oauth2" = [])
140 )
141)]
142#[put("")]
143pub async fn update(
144 path: Path<i32>,
145 update: Json<ActionDtoWrapperUpdateLayer>,
146 pool: SharedPool,
147 broadcaster: SharedBroadcaster,
148 user_info: UserInfo,
149) -> Result<HttpResponse> {
150 let ActionDtoWrapper { action_id, dto } = update.into_inner();
151 let map_id = path.into_inner();
152 let user_id = user_info.id;
153
154 let action = layer::update(map_id, dto.clone(), &pool).await?;
155
156 broadcaster
157 .broadcast(
158 map_id,
159 Action {
160 action_id,
161 user_id,
162 action,
163 },
164 )
165 .await;
166
167 Ok(HttpResponse::Ok().finish())
168}
169
170#[utoipa::path(
176 context_path = "/api/maps/{map_id}/layers",
177 params(
178 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
179 ),
180 request_body = ActionDtoWrapperDeleteLayer,
181 responses(
182 (status = 200, description = "Delete a layer")
183 ),
184 security(
185 ("oauth2" = [])
186 )
187)]
188#[delete("")]
189pub async fn delete(
190 path: Path<i32>,
191 delete_layer: Json<ActionDtoWrapperDeleteLayer>,
192 pool: SharedPool,
193 broadcaster: SharedBroadcaster,
194 user_info: UserInfo,
195) -> Result<HttpResponse> {
196 let ActionDtoWrapper { action_id, dto } = delete_layer.into_inner();
197 let map_id = path.into_inner();
198 let user_id = user_info.id;
199 let layer_id = dto.id;
200
201 layer::delete_by_id(map_id, layer_id, &pool).await?;
202
203 broadcaster
204 .broadcast(
205 map_id,
206 Action {
207 action_id,
208 user_id,
209 action: ActionType::DeleteLayer(layer_id),
210 },
211 )
212 .await;
213
214 Ok(HttpResponse::Ok().finish())
215}