1use actix_web::{
4 delete, get, patch, post,
5 web::{Json, Path},
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, UpdateDrawingNotesActionPayload},
17 core::ActionDtoWrapper,
18 drawings::{DrawingDto, UpdateDrawingsDto},
19 },
20 service::{self, map_access_control::check_permissions},
21};
22
23#[utoipa::path(
28 context_path = "/api/maps/{map_id}/drawings",
29 params(
30 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
31 ),
32 responses(
33 (status = 200, description = "Find drawings", body = Vec<DrawingDto>)
34 ),
35 security(
36 ("oauth2" = [])
37 )
38)]
39#[get("")]
40pub async fn find(
41 map_id: Path<i32>,
42 pool: SharedPool,
43 user_info: UserInfo,
44) -> Result<HttpResponse> {
45 let id = map_id.into_inner();
46 check_permissions(id, &pool, user_info).await?;
47 let response = service::drawings::find(id, &pool).await?;
48 Ok(HttpResponse::Ok().json(response))
49}
50
51#[utoipa::path(
56 context_path = "/api/maps/{map_id}/drawings",
57 params(
58 ("map_id" = i32, Path, description = "The id of the map"),
59 ),
60 request_body = ActionDtoWrapperNewPlantings,
61 responses(
62 (status = 201, description = "Create plantings", body = Vec<DrawingDto>)
63 ),
64 security(
65 ("oauth2" = [])
66 )
67)]
68#[post("")]
69pub async fn create(
70 path: Path<i32>,
71 new_drawings: Json<ActionDtoWrapper<Vec<DrawingDto>>>,
72 pool: SharedPool,
73 broadcaster: SharedBroadcaster,
74 user_info: UserInfo,
75) -> Result<HttpResponse> {
76 let map_id = path.into_inner();
77 let id = user_info.id;
78 check_permissions(map_id, &pool, user_info).await?;
79
80 let ActionDtoWrapper { action_id, dto } = new_drawings.into_inner();
81
82 let created_drawings = service::drawings::create(dto, &pool).await?;
83
84 broadcaster
85 .broadcast(
86 map_id,
87 Action {
88 action_id,
89 user_id: id,
90 action: ActionType::CreateDrawing(created_drawings.clone()),
91 },
92 )
93 .await;
94
95 Ok(HttpResponse::Created().json(created_drawings))
96}
97
98#[utoipa::path(
103 context_path = "/api/maps/{map_id}/drawings",
104 params(
105 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
106 ),
107 request_body = ActionDtoWrapperUpdatePlantings,
108 responses(
109 (status = 200, description = "Update plantings", body = Vec<DrawingDto>)
110 ),
111 security(
112 ("oauth2" = [])
113 )
114)]
115#[patch("")]
116pub async fn update(
117 path: Path<i32>,
118 update_drawings: Json<ActionDtoWrapper<UpdateDrawingsDto>>,
119 pool: SharedPool,
120 broadcaster: SharedBroadcaster,
121 user_info: UserInfo,
122) -> Result<HttpResponse> {
123 let map_id = path.into_inner();
124 let id = user_info.id;
125 check_permissions(map_id, &pool, user_info).await?;
126 let ActionDtoWrapper { action_id, dto } = update_drawings.into_inner();
127
128 let updated = service::drawings::update(dto.clone(), &pool).await?;
129
130 let action = match &dto {
131 UpdateDrawingsDto::Update(_) => ActionType::UpdateDrawing(updated.clone()),
132 UpdateDrawingsDto::UpdateAddDate(_) => ActionType::UpdateDrawingAddDate(updated.clone()),
133 UpdateDrawingsDto::UpdateRemoveDate(_) => {
134 ActionType::UpdateDrawingRemoveDate(updated.clone())
135 }
136 UpdateDrawingsDto::UpdateNotes(_) => ActionType::UpdateDrawingNotes(
137 updated
138 .clone()
139 .into_iter()
140 .map(UpdateDrawingNotesActionPayload::new)
141 .collect(),
142 ),
143 };
144
145 broadcaster
146 .broadcast(
147 map_id,
148 Action {
149 action_id,
150 user_id: id,
151 action,
152 },
153 )
154 .await;
155
156 Ok(HttpResponse::Ok().json(updated))
157}
158
159#[utoipa::path(
164 context_path = "/api/maps/{map_id}/drawings",
165 params(
166 ("map_id" = i32, Path, description = "The id of the map"),
167 ),
168 request_body = ActionDtoWrapperDeleteDrawings,
169 responses(
170 (status = 200, description = "Drawings have been deleted")
171 ),
172 security(
173 ("oauth2" = [])
174 )
175)]
176#[delete("")]
177pub async fn delete(
178 path: Path<i32>,
179 delete_drawings: Json<ActionDtoWrapper<Vec<Uuid>>>,
180 pool: SharedPool,
181 broadcaster: SharedBroadcaster,
182 user_info: UserInfo,
183) -> Result<HttpResponse> {
184 let map_id = path.into_inner();
185 let id = user_info.id;
186 check_permissions(map_id, &pool, user_info).await?;
187 let ActionDtoWrapper { action_id, dto } = delete_drawings.into_inner();
188
189 service::drawings::delete_by_ids(dto.clone(), &pool).await?;
190
191 broadcaster
192 .broadcast(
193 map_id,
194 Action {
195 action_id,
196 user_id: id,
197 action: ActionType::DeleteDrawing(dto),
198 },
199 )
200 .await;
201
202 Ok(HttpResponse::Ok().finish())
203}