1#![allow(clippy::missing_docs_in_private_items)]
7#![allow(clippy::missing_const_for_fn)]
9
10use chrono::NaiveDate;
11use postgis_diesel::types::{Point, Polygon};
12use serde::Serialize;
13use typeshare::typeshare;
14use uuid::Uuid;
15
16use crate::model::dto::{
17 areas::{AreaDto, AreaKind, AreaType},
18 base_layer_images::BaseLayerImageDto,
19 drawings::DrawingDto,
20 layers::{LayerDto, LayerRenameDto},
21 plantings::{
22 DeletePlantingDto, MovePlantingDto, PlantingDto, TransformPlantingDto,
23 UpdateAddDatePlantingDto, UpdatePlantingNoteDto, UpdateRemoveDatePlantingDto,
24 },
25 UpdateMapGeometryDto,
26};
27
28#[typeshare]
29#[derive(Debug, Serialize, Clone)]
30#[serde(rename_all = "camelCase")]
31pub struct Action {
32 pub action_id: Uuid,
33 pub user_id: Uuid,
34 pub action: ActionType,
35}
36
37#[typeshare]
38#[derive(Debug, Serialize, Clone)]
39#[serde(tag = "type", content = "payload")]
42pub enum ActionType {
43 CreateLayer(LayerDto),
45 DeleteLayer(Uuid),
48 RestoreDrawingLayer(RestoreDrawingLayerActionPayload),
51 RenameLayer(LayerRenameDto),
53 ReorderLayers(Vec<Uuid>),
55
56 CreatePlanting(Vec<PlantingDto>),
58 DeletePlanting(Vec<DeletePlantingActionPayload>),
60 MovePlanting(Vec<MovePlantingActionPayload>),
62 TransformPlanting(Vec<TransformPlantingActionPayload>),
64 UpdatePlantingAddDate(Vec<UpdateAddDateActionPayload>),
66 UpdatePlantingRemoveDate(Vec<UpdateRemoveDateActionPayload>),
68 UpdatePlantingNotes(Vec<UpdatePlantingNotesActionPayload>),
70
71 CreateShading(Vec<AreaDto>),
73 DeleteShading(Vec<Uuid>),
75 UpdateShading(Vec<UpdateAreaActionPayload>),
77 UpdateShadingAddDate(Vec<UpdateAreaAddDateActionPayload>),
79 UpdateShadingRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
81 UpdateShadingNotes(Vec<UpdateAreaNotesActionPayload>),
83
84 CreateHydrology(Vec<AreaDto>),
86 DeleteHydrology(Vec<Uuid>),
88 UpdateHydrology(Vec<UpdateAreaActionPayload>),
90 UpdateHydrologyAddDate(Vec<UpdateAreaAddDateActionPayload>),
92 UpdateHydrologyRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
94 UpdateHydrologyNotes(Vec<UpdateAreaNotesActionPayload>),
96
97 CreateSoilTexture(Vec<AreaDto>),
99 DeleteSoilTexture(Vec<Uuid>),
101 UpdateSoilTexture(Vec<UpdateAreaActionPayload>),
103 UpdateSoilTextureAddDate(Vec<UpdateAreaAddDateActionPayload>),
105 UpdateSoilTextureRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
107 UpdateSoilTextureNotes(Vec<UpdateAreaNotesActionPayload>),
109
110 CreateBaseLayerImage(CreateBaseLayerImageActionPayload),
112 UpdateBaseLayerImage(UpdateBaseLayerImageActionPayload),
114 DeleteBaseLayerImage(DeleteBaseLayerImageActionPayload),
116 UpdateMapGeometry(UpdateMapGeometryActionPayload),
118 UpdatePlantingAdditionalName(UpdatePlantingAdditionalNamePayload),
120
121 CreateDrawing(Vec<DrawingDto>),
123 DeleteDrawing(Vec<Uuid>),
125 UpdateDrawing(Vec<DrawingDto>),
127 UpdateDrawingAddDate(Vec<DrawingDto>),
129 UpdateDrawingRemoveDate(Vec<DrawingDto>),
131 UpdateDrawingNotes(Vec<UpdateDrawingNotesActionPayload>),
133}
134
135impl Action {
136 #[must_use]
137 pub fn new_create_planting_action(
138 dtos: Vec<PlantingDto>,
139 user_id: Uuid,
140 action_id: Uuid,
141 ) -> Self {
142 Self {
143 action_id,
144 user_id,
145 action: ActionType::CreatePlanting(dtos),
146 }
147 }
148
149 #[must_use]
150 pub fn new_delete_planting_action(
151 dtos: &[DeletePlantingDto],
152 user_id: Uuid,
153 action_id: Uuid,
154 ) -> Self {
155 Self {
156 action_id,
157 user_id,
158 action: ActionType::DeletePlanting(
159 dtos.iter()
160 .map(|dto| DeletePlantingActionPayload { id: dto.id })
161 .collect(),
162 ),
163 }
164 }
165
166 #[must_use]
167 pub fn new_move_planting_action(
168 dtos: &[MovePlantingDto],
169 user_id: Uuid,
170 action_id: Uuid,
171 ) -> Self {
172 Self {
173 action_id,
174 user_id,
175 action: ActionType::MovePlanting(
176 dtos.iter()
177 .map(|dto| MovePlantingActionPayload {
178 id: dto.id,
179 x: dto.x,
180 y: dto.y,
181 })
182 .collect(),
183 ),
184 }
185 }
186
187 #[must_use]
188 pub fn new_transform_planting_action(
189 dtos: &[TransformPlantingDto],
190 user_id: Uuid,
191 action_id: Uuid,
192 ) -> Self {
193 Self {
194 action_id,
195 user_id,
196 action: ActionType::TransformPlanting(
197 dtos.iter()
198 .map(|dto| TransformPlantingActionPayload {
199 id: dto.id,
200 x: dto.x,
201 y: dto.y,
202 rotation: dto.rotation,
203 size_x: dto.size_x,
204 size_y: dto.size_y,
205 height: dto.height,
206 })
207 .collect(),
208 ),
209 }
210 }
211
212 #[must_use]
213 pub fn new_update_planting_add_date_action(
214 dtos: &[UpdateAddDatePlantingDto],
215 user_id: Uuid,
216 action_id: Uuid,
217 ) -> Self {
218 Self {
219 action_id,
220 user_id,
221 action: ActionType::UpdatePlantingAddDate(
222 dtos.iter()
223 .map(|dto| UpdateAddDateActionPayload {
224 id: dto.id,
225 add_date: dto.add_date,
226 })
227 .collect(),
228 ),
229 }
230 }
231
232 #[must_use]
233 pub fn new_update_planting_remove_date_action(
234 dtos: &[UpdateRemoveDatePlantingDto],
235 user_id: Uuid,
236 action_id: Uuid,
237 ) -> Self {
238 Self {
239 action_id,
240 user_id,
241 action: ActionType::UpdatePlantingRemoveDate(
242 dtos.iter()
243 .map(|dto| UpdateRemoveDateActionPayload {
244 id: dto.id,
245 remove_date: dto.remove_date,
246 })
247 .collect(),
248 ),
249 }
250 }
251
252 #[must_use]
253 pub fn new_update_planting_note_action(
254 dtos: &[UpdatePlantingNoteDto],
255 user_id: Uuid,
256 action_id: Uuid,
257 ) -> Self {
258 Self {
259 action_id,
260 user_id,
261 action: ActionType::UpdatePlantingNotes(
262 dtos.iter()
263 .map(|dto| UpdatePlantingNotesActionPayload {
264 id: dto.id,
265 notes: dto.notes.clone(),
266 })
267 .collect(),
268 ),
269 }
270 }
271
272 #[must_use]
273 pub fn new_create_area_action(
274 area_kind: AreaKind,
275 dtos: Vec<AreaDto>,
276 user_id: Uuid,
277 action_id: Uuid,
278 ) -> Self {
279 Self {
280 action_id,
281 user_id,
282 action: match area_kind {
283 AreaKind::Shade => ActionType::CreateShading(dtos),
284 AreaKind::Hydrology => ActionType::CreateHydrology(dtos),
285 AreaKind::SoilTexture => ActionType::CreateSoilTexture(dtos),
286 },
287 }
288 }
289
290 #[must_use]
291 pub fn new_update_area_action(
292 area_kind: AreaKind,
293 dtos: &[AreaDto],
294 user_id: Uuid,
295 action_id: Uuid,
296 ) -> Self {
297 let payload = dtos
298 .iter()
299 .map(|dto| UpdateAreaActionPayload {
300 id: dto.id,
301 area_type: dto.area_type.clone(),
302 })
303 .collect();
304 Self {
305 action_id,
306 user_id,
307 action: match area_kind {
308 AreaKind::Shade => ActionType::UpdateShading(payload),
309 AreaKind::Hydrology => ActionType::UpdateHydrology(payload),
310 AreaKind::SoilTexture => ActionType::UpdateSoilTexture(payload),
311 },
312 }
313 }
314
315 #[must_use]
316 pub fn new_update_area_add_date_action(
317 area_kind: AreaKind,
318 dtos: &[AreaDto],
319 user_id: Uuid,
320 action_id: Uuid,
321 ) -> Self {
322 let payload = dtos
323 .iter()
324 .map(|dto| UpdateAreaAddDateActionPayload {
325 id: dto.id,
326 add_date: dto.add_date,
327 })
328 .collect();
329 Self {
330 action_id,
331 user_id,
332 action: match area_kind {
333 AreaKind::Shade => ActionType::UpdateShadingAddDate(payload),
334 AreaKind::Hydrology => ActionType::UpdateHydrologyAddDate(payload),
335 AreaKind::SoilTexture => ActionType::UpdateSoilTextureAddDate(payload),
336 },
337 }
338 }
339
340 #[must_use]
341 pub fn new_update_area_remove_date_action(
342 area_kind: AreaKind,
343 dtos: &[AreaDto],
344 user_id: Uuid,
345 action_id: Uuid,
346 ) -> Self {
347 let payload = dtos
348 .iter()
349 .map(|dto| UpdateAreaRemoveDateActionPayload {
350 id: dto.id,
351 remove_date: dto.remove_date,
352 })
353 .collect();
354 Self {
355 action_id,
356 user_id,
357 action: match area_kind {
358 AreaKind::Shade => ActionType::UpdateShadingRemoveDate(payload),
359 AreaKind::Hydrology => ActionType::UpdateHydrologyRemoveDate(payload),
360 AreaKind::SoilTexture => ActionType::UpdateSoilTextureRemoveDate(payload),
361 },
362 }
363 }
364
365 #[must_use]
366 pub fn new_update_area_notes_action(
367 area_kind: AreaKind,
368 dtos: &[AreaDto],
369 user_id: Uuid,
370 action_id: Uuid,
371 ) -> Self {
372 let payload: Vec<UpdateAreaNotesActionPayload> = dtos
373 .iter()
374 .map(|dto| UpdateAreaNotesActionPayload {
375 id: dto.id,
376 notes: dto.notes.clone(),
377 })
378 .collect();
379 Self {
380 action_id,
381 user_id,
382 action: match area_kind {
383 AreaKind::Shade => ActionType::UpdateShadingNotes(payload),
384 AreaKind::Hydrology => ActionType::UpdateHydrologyNotes(payload),
385 AreaKind::SoilTexture => ActionType::UpdateSoilTextureNotes(payload),
386 },
387 }
388 }
389
390 #[must_use]
391 pub fn new_delete_area_action(
392 area_kind: AreaKind,
393 ids: Vec<Uuid>,
394 user_id: Uuid,
395 action_id: Uuid,
396 ) -> Self {
397 Self {
398 action_id,
399 user_id,
400 action: match area_kind {
401 AreaKind::Shade => ActionType::DeleteShading(ids),
402 AreaKind::Hydrology => ActionType::DeleteHydrology(ids),
403 AreaKind::SoilTexture => ActionType::DeleteSoilTexture(ids),
404 },
405 }
406 }
407}
408
409#[typeshare]
410#[derive(Debug, Serialize, Clone)]
411#[serde(rename_all = "camelCase")]
413pub struct RestoreDrawingLayerActionPayload {
414 id: Uuid,
416 drawings: Vec<DrawingDto>,
418}
419
420impl RestoreDrawingLayerActionPayload {
421 #[must_use]
422 pub fn new(id: Uuid, drawings: Vec<DrawingDto>) -> Self {
423 Self { id, drawings }
424 }
425}
426
427#[typeshare]
428#[derive(Debug, Serialize, Clone)]
429#[serde(rename_all = "camelCase")]
432pub struct CreatePlantActionPayload {
433 id: Uuid,
434 layer_id: Uuid,
435 plant_id: i32,
436 x: i32,
437 y: i32,
438 rotation: f32,
439 size_x: i32,
440 size_y: i32,
441 height: Option<i32>,
442 add_date: Option<NaiveDate>,
443 remove_date: Option<NaiveDate>,
444 seed_id: Option<i32>,
445 additional_name: Option<String>,
446 is_area: bool,
447}
448
449#[typeshare]
450#[derive(Debug, Serialize, Clone)]
451#[serde(rename_all = "camelCase")]
453pub struct DeletePlantingActionPayload {
454 id: Uuid,
455}
456
457#[typeshare]
458#[derive(Debug, Serialize, Clone)]
459#[serde(rename_all = "camelCase")]
461pub struct MovePlantingActionPayload {
462 id: Uuid,
463 x: i32,
464 y: i32,
465}
466
467#[typeshare]
468#[derive(Debug, Serialize, Clone)]
469#[serde(rename_all = "camelCase")]
471pub struct TransformPlantingActionPayload {
472 id: Uuid,
473 x: i32,
474 y: i32,
475 rotation: f32,
476 size_x: i32,
477 size_y: i32,
478 height: Option<i32>,
479}
480
481#[typeshare]
482#[derive(Debug, Serialize, Clone)]
483#[serde(rename_all = "camelCase")]
484pub struct CreateShadingActionPayload {
485 id: Uuid,
486 layer_id: Uuid,
487 area_type: AreaType,
488 geometry: Polygon<Point>,
489 add_date: Option<NaiveDate>,
490 remove_date: Option<NaiveDate>,
491 notes: String,
492}
493
494#[typeshare]
495#[derive(Debug, Serialize, Clone)]
496#[serde(rename_all = "camelCase")]
497pub struct CreateHydrologyActionPayload {
498 id: Uuid,
499 layer_id: Uuid,
500 area_type: AreaType,
501 geometry: Polygon<Point>,
502 add_date: Option<NaiveDate>,
503 remove_date: Option<NaiveDate>,
504 notes: String,
505}
506
507#[typeshare]
508#[derive(Debug, Serialize, Clone)]
509#[serde(rename_all = "camelCase")]
510pub struct CreateAreaActionPayload {
511 id: Uuid,
512 layer_id: Uuid,
513 area_type: AreaType,
514 geometry: Polygon<Point>,
515 add_date: Option<NaiveDate>,
516 remove_date: Option<NaiveDate>,
517 notes: String,
518}
519
520impl CreateAreaActionPayload {
521 #[must_use]
522 pub fn new(payload: AreaDto) -> Self {
523 Self {
524 id: payload.id,
525 layer_id: payload.layer_id,
526 area_type: payload.area_type,
527 geometry: payload.geometry,
528 add_date: payload.add_date,
529 remove_date: payload.remove_date,
530 notes: payload.notes,
531 }
532 }
533}
534
535#[typeshare]
536#[derive(Debug, Serialize, Clone)]
537#[serde(rename_all = "camelCase")]
539pub struct UpdateAreaActionPayload {
540 id: Uuid,
541 area_type: AreaType,
542}
543
544impl UpdateAreaActionPayload {
545 #[must_use]
546 pub fn new(payload: AreaDto) -> Self {
547 Self {
548 id: payload.id,
549 area_type: payload.area_type,
550 }
551 }
552}
553
554#[typeshare]
555#[derive(Debug, Serialize, Clone)]
556#[serde(rename_all = "camelCase")]
558pub struct UpdateAreaAddDateActionPayload {
559 id: Uuid,
560 add_date: Option<NaiveDate>,
561}
562
563impl UpdateAreaAddDateActionPayload {
564 #[must_use]
565 pub fn new(payload: &AreaDto) -> Self {
566 Self {
567 id: payload.id,
568 add_date: payload.add_date,
569 }
570 }
571}
572
573#[typeshare]
574#[derive(Debug, Serialize, Clone)]
575#[serde(rename_all = "camelCase")]
577pub struct UpdateAreaRemoveDateActionPayload {
578 id: Uuid,
579 remove_date: Option<NaiveDate>,
580}
581
582impl UpdateAreaRemoveDateActionPayload {
583 #[must_use]
584 pub fn new(payload: &AreaDto) -> Self {
585 Self {
586 id: payload.id,
587 remove_date: payload.remove_date,
588 }
589 }
590}
591
592#[typeshare]
593#[derive(Debug, Serialize, Clone)]
594pub struct UpdateAreaNotesActionPayload {
596 id: Uuid,
597 notes: String,
598}
599
600impl UpdateAreaNotesActionPayload {
601 #[must_use]
602 pub fn new(payload: &AreaDto) -> Self {
603 Self {
604 id: payload.id,
605 notes: payload.notes.clone(),
606 }
607 }
608}
609
610#[typeshare]
611#[derive(Debug, Serialize, Clone)]
612#[serde(rename_all = "camelCase")]
614pub struct UpdatePlantingNotesActionPayload {
615 id: Uuid,
616 notes: String,
617}
618
619#[typeshare]
620#[derive(Debug, Serialize, Clone)]
621#[serde(rename_all = "camelCase")]
624pub struct CreateBaseLayerImageActionPayload {
625 id: Uuid,
626 layer_id: Uuid,
627 rotation: f32,
628 scale: f32,
629 path: String,
630}
631
632impl CreateBaseLayerImageActionPayload {
633 #[must_use]
634 pub fn new(payload: BaseLayerImageDto) -> Self {
635 Self {
636 id: payload.id,
637 layer_id: payload.layer_id,
638 rotation: payload.rotation,
639 scale: payload.scale,
640 path: payload.path,
641 }
642 }
643}
644
645#[typeshare]
646#[derive(Debug, Serialize, Clone)]
647#[serde(rename_all = "camelCase")]
649pub struct DeleteBaseLayerImageActionPayload {
650 id: Uuid,
651}
652
653impl DeleteBaseLayerImageActionPayload {
654 #[must_use]
655 pub fn new(id: Uuid) -> Self {
656 Self { id }
657 }
658}
659
660#[typeshare]
661#[derive(Debug, Serialize, Clone)]
662#[serde(rename_all = "camelCase")]
664pub struct UpdateBaseLayerImageActionPayload {
665 id: Uuid,
666 layer_id: Uuid,
667 rotation: f32,
668 scale: f32,
669 path: String,
670 x: i32,
671 y: i32,
672}
673
674impl UpdateBaseLayerImageActionPayload {
675 #[must_use]
676 pub fn new(payload: BaseLayerImageDto) -> Self {
677 Self {
678 id: payload.id,
679 layer_id: payload.layer_id,
680 rotation: payload.rotation,
681 scale: payload.scale,
682 path: payload.path,
683 x: payload.x,
684 y: payload.y,
685 }
686 }
687}
688
689#[typeshare]
690#[derive(Debug, Serialize, Clone)]
691#[serde(rename_all = "camelCase")]
693pub struct UpdateAddDateActionPayload {
694 id: Uuid,
695 add_date: Option<NaiveDate>,
696}
697
698#[typeshare]
699#[derive(Debug, Serialize, Clone)]
700#[serde(rename_all = "camelCase")]
702pub struct UpdateRemoveDateActionPayload {
703 id: Uuid,
704 remove_date: Option<NaiveDate>,
705}
706
707#[typeshare]
708#[derive(Debug, Serialize, Clone)]
709#[serde(rename_all = "camelCase")]
711pub struct UpdateMapGeometryActionPayload {
712 map_id: i32,
714 #[typeshare(serialized_as = "object")]
716 geometry: Polygon<Point>,
717}
718
719impl UpdateMapGeometryActionPayload {
720 #[must_use]
721 pub fn new(payload: UpdateMapGeometryDto, map_id: i32) -> Self {
722 Self {
723 map_id,
724 geometry: payload.geometry,
725 }
726 }
727}
728
729#[typeshare]
730#[derive(Debug, Serialize, Clone)]
731#[serde(rename_all = "camelCase")]
733pub struct UpdatePlantingAdditionalNamePayload {
734 id: Uuid,
735 additional_name: Option<String>,
736}
737
738impl UpdatePlantingAdditionalNamePayload {
739 #[must_use]
740 pub fn new(payload: &PlantingDto, new_additional_name: Option<String>) -> Self {
741 Self {
742 id: payload.id,
743 additional_name: new_additional_name,
744 }
745 }
746}
747
748#[typeshare]
749#[derive(Debug, Serialize, Clone)]
750#[serde(rename_all = "camelCase")]
752pub struct UpdateDrawingNotesActionPayload {
753 id: Uuid,
754 notes: String,
755}
756
757impl UpdateDrawingNotesActionPayload {
758 #[must_use]
759 pub fn new(drawing: DrawingDto) -> Self {
760 Self {
761 id: drawing.id,
762 notes: drawing.notes,
763 }
764 }
765}