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, 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 = plantings::update(dto.clone(), map_id, user_info.id, &pool).await?;
122
123 let action = match &dto {
124 UpdatePlantingDto::Transform(dto) => {
125 Action::new_transform_planting_action(dto, user_info.id, action_id)
126 }
127 UpdatePlantingDto::Move(dto) => {
128 Action::new_move_planting_action(dto, user_info.id, action_id)
129 }
130 UpdatePlantingDto::UpdateAddDate(dto) => {
131 Action::new_update_planting_add_date_action(dto, user_info.id, action_id)
132 }
133 UpdatePlantingDto::UpdateRemoveDate(dto) => {
134 Action::new_update_planting_remove_date_action(dto, user_info.id, action_id)
135 }
136 UpdatePlantingDto::UpdateNote(dto) => {
137 Action::new_update_planting_note_action(dto, user_info.id, action_id)
138 }
139 };
140
141 broadcaster.broadcast(map_id, action).await;
142
143 Ok(HttpResponse::Ok().json(updated_plantings))
144}
145
146#[utoipa::path(
151 context_path = "/api/maps/{map_id}/layers/plants/plantings",
152 params(
153 ("map_id" = i32, Path, description = "The id of the map the layer is on"),
154 ),
155 request_body = ActionDtoWrapperDeletePlantings,
156 responses(
157 (status = 200, description = "Delete plantings")
158 ),
159 security(
160 ("oauth2" = [])
161 )
162)]
163#[delete("")]
164pub async fn delete(
165 path: Path<i32>,
166 delete_planting: Json<ActionDtoWrapper<Vec<DeletePlantingDto>>>,
167 user_info: UserInfo,
168 pool: SharedPool,
169 broadcaster: SharedBroadcaster,
170) -> Result<HttpResponse> {
171 let map_id = path.into_inner();
172
173 let ActionDtoWrapper { action_id, dto } = delete_planting.into_inner();
174
175 plantings::delete_by_ids(dto.clone(), map_id, user_info.id, &pool).await?;
176
177 broadcaster
178 .broadcast(
179 map_id,
180 Action::new_delete_planting_action(&dto, user_info.id, action_id),
181 )
182 .await;
183
184 Ok(HttpResponse::Ok().finish())
185}