1use actix_web::{
4 delete, get, patch, post,
5 web::{Json, Path, Query},
6 HttpResponse, Result,
7};
8
9use crate::{
10 config::{
11 auth::user_info::UserInfo,
12 data::{SharedBroadcaster, SharedPool},
13 },
14 model::dto::{
15 actions::Action,
16 core::ActionDtoWrapper,
17 plantings::{DeletePlantingDto, PlantingDto, PlantingSearchParameters, UpdatePlantingDto},
18 },
19 service::plantings,
20};
21
22#[utoipa::path(
27 context_path = "/api/maps/{map_id}/layers/plants/plantings",
28 params(
29 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
30 PlantingSearchParameters
31 ),
32 responses(
33 (status = 200, description = "Find plantings", body = TimelinePagePlantingsDto)
34 ),
35 security(
36 ("oauth2" = [])
37 )
38)]
39#[get("")]
40pub async fn find(
41 _map_id: Path<i32>,
44 search_params: Query<PlantingSearchParameters>,
45 pool: SharedPool,
46) -> Result<HttpResponse> {
47 let response = plantings::find(search_params.into_inner(), &pool).await?;
48 Ok(HttpResponse::Ok().json(response))
49}
50
51#[utoipa::path(
56 context_path = "/api/maps/{map_id}/layers/plants/plantings",
57 params(
58 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
59 ),
60 request_body = ActionDtoWrapperNewPlantings,
61 responses(
62 (status = 201, description = "Create plantings", body = Vec<PlantingDto>)
63 ),
64 security(
65 ("oauth2" = [])
66 )
67)]
68#[post("")]
69pub async fn create(
70 path: Path<i32>,
71 new_plantings: Json<ActionDtoWrapper<Vec<PlantingDto>>>,
72 user_info: UserInfo,
73 pool: SharedPool,
74 broadcaster: SharedBroadcaster,
75) -> Result<HttpResponse> {
76 let map_id = path.into_inner();
77
78 let ActionDtoWrapper { action_id, dto } = new_plantings.into_inner();
79
80 let created_plantings = plantings::create(dto, map_id.into(), user_info.id, &pool).await?;
81
82 broadcaster
83 .broadcast(
84 map_id,
85 Action::new_create_planting_action(created_plantings.clone(), user_info.id, action_id),
86 )
87 .await;
88
89 Ok(HttpResponse::Created().json(created_plantings))
90}
91
92#[utoipa::path(
97 context_path = "/api/maps/{map_id}/layers/plants/plantings",
98 params(
99 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
100 ),
101 request_body = ActionDtoWrapperUpdatePlantings,
102 responses(
103 (status = 200, description = "Update plantings", body = Vec<PlantingDto>)
104 ),
105 security(
106 ("oauth2" = [])
107 )
108)]
109#[patch("")]
110pub async fn update(
111 path: Path<i32>,
112 update_planting: Json<ActionDtoWrapper<UpdatePlantingDto>>,
113 user_info: UserInfo,
114 pool: SharedPool,
115 broadcaster: SharedBroadcaster,
116) -> Result<HttpResponse> {
117 let map_id = path.into_inner();
118
119 let ActionDtoWrapper { action_id, dto } = update_planting.into_inner();
120
121 let updated_plantings =
122 plantings::update(dto.clone(), map_id.into(), user_info.id, &pool).await?;
123
124 let action = match &dto {
125 UpdatePlantingDto::Transform(dto) => {
126 Action::new_transform_planting_action(dto, user_info.id, action_id)
127 }
128 UpdatePlantingDto::Move(dto) => {
129 Action::new_move_planting_action(dto, user_info.id, action_id)
130 }
131 UpdatePlantingDto::UpdateAddDate(dto) => {
132 Action::new_update_planting_add_date_action(dto, user_info.id, action_id)
133 }
134 UpdatePlantingDto::UpdateRemoveDate(dto) => {
135 Action::new_update_planting_remove_date_action(dto, user_info.id, action_id)
136 }
137 UpdatePlantingDto::UpdateNote(dto) => {
138 Action::new_update_planting_note_action(dto, user_info.id, action_id)
139 }
140 };
141
142 broadcaster.broadcast(map_id, action).await;
143
144 Ok(HttpResponse::Ok().json(updated_plantings))
145}
146
147#[utoipa::path(
152 context_path = "/api/maps/{map_id}/layers/plants/plantings",
153 params(
154 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
155 ),
156 request_body = ActionDtoWrapperDeletePlantings,
157 responses(
158 (status = 200, description = "Delete plantings")
159 ),
160 security(
161 ("oauth2" = [])
162 )
163)]
164#[delete("")]
165pub async fn delete(
166 path: Path<i32>,
167 delete_planting: Json<ActionDtoWrapper<Vec<DeletePlantingDto>>>,
168 user_info: UserInfo,
169 pool: SharedPool,
170 broadcaster: SharedBroadcaster,
171) -> Result<HttpResponse> {
172 let map_id = path.into_inner();
173
174 let ActionDtoWrapper { action_id, dto } = delete_planting.into_inner();
175
176 plantings::delete_by_ids(dto.clone(), map_id.into(), user_info.id, &pool).await?;
177
178 broadcaster
179 .broadcast(
180 map_id,
181 Action::new_delete_planting_action(&dto, user_info.id, action_id),
182 )
183 .await;
184
185 Ok(HttpResponse::Ok().finish())
186}