backend/model/dto/
actions.rs

1//! Contains all the actions that can be broadcasted via [`crate::sse::broadcaster::Broadcaster`].
2
3// The properties of the actions are not documented because they are
4// self-explanatory and should be already documented in the respective
5// entity DTOs.
6#![allow(clippy::missing_docs_in_private_items)]
7// Don't make the `new` functions const, there might come more fields in the future.
8#![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
28const SYSTEM_USER_ID: Uuid = Uuid::from_u128(0);
29
30#[typeshare]
31#[derive(Debug, Serialize, Clone)]
32#[serde(rename_all = "camelCase")]
33pub struct Action {
34    pub action_id: Uuid,
35    pub user_id: Uuid,
36    pub action: ActionType,
37}
38
39#[typeshare]
40#[derive(Debug, Serialize, Clone)]
41// Use the name of the enum variant as the type field looking like { "type": "CreatePlanting", ... }.
42/// An enum representing all the actions that can be broadcasted via [`crate::sse::broadcaster::Broadcaster`].
43#[serde(tag = "type", content = "payload")]
44pub enum ActionType {
45    /// An action used to broadcast creation of a layer.
46    CreateLayer(LayerDto),
47    /// An action used to broadcast soft-deletion of a layer.
48    /// Deleted layers can be restored.
49    DeleteLayer(Uuid),
50    /// An action used to broadcast restoration of a deleted layer.
51    /// Restore is only supported for drawing layers
52    RestoreDrawingLayer(RestoreDrawingLayerActionPayload),
53    /// An action used to broadcast the renaming of a layer.
54    RenameLayer(LayerRenameDto),
55    /// An action used to broadcast the reordering of multiple layers.
56    ReorderLayers(Vec<Uuid>),
57
58    /// An action used to broadcast creation of plantings.
59    CreatePlanting(Vec<PlantingDto>),
60    /// An action used to broadcast deletion of plantings.
61    DeletePlanting(Vec<DeletePlantingActionPayload>),
62    /// An action used to broadcast movement of plantings.
63    MovePlanting(Vec<MovePlantingActionPayload>),
64    /// An action used to broadcast transformation of plantings.
65    TransformPlanting(Vec<TransformPlantingActionPayload>),
66    /// An action used to update the `add_date` of plantings.
67    UpdatePlantingAddDate(Vec<UpdateAddDateActionPayload>),
68    /// An action used to update the `remove_date` of plantings.
69    UpdatePlantingRemoveDate(Vec<UpdateRemoveDateActionPayload>),
70    /// An action used to broadcast updating Markdown notes of plantings.
71    UpdatePlantingNotes(Vec<UpdatePlantingNotesActionPayload>),
72
73    /// An action used to broadcast creation of shading.
74    CreateShading(Vec<AreaDto>),
75    /// An action used to broadcast deletion of shading.
76    DeleteShading(Vec<Uuid>),
77    /// An action used to broadcast change of shading.
78    UpdateShading(Vec<UpdateAreaActionPayload>),
79    /// An action used to update `add_date` of shading.
80    UpdateShadingAddDate(Vec<UpdateAreaAddDateActionPayload>),
81    /// An action used to update `remove_date` of shading.
82    UpdateShadingRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
83    /// An action used to update `notes` of shading.
84    UpdateShadingNotes(Vec<UpdateAreaNotesActionPayload>),
85
86    /// An action used to broadcast creation of hydrology.
87    CreateHydrology(Vec<AreaDto>),
88    /// An action used to broadcast deletion of hydrology.
89    DeleteHydrology(Vec<Uuid>),
90    /// An action used to broadcast change of hydrology.
91    UpdateHydrology(Vec<UpdateAreaActionPayload>),
92    /// An action used to update `add_date` of hydrology.
93    UpdateHydrologyAddDate(Vec<UpdateAreaAddDateActionPayload>),
94    /// An action used to update `remove_date` of hydrology.
95    UpdateHydrologyRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
96    /// An action used to update `notes` of hydrology.
97    UpdateHydrologyNotes(Vec<UpdateAreaNotesActionPayload>),
98
99    /// An action used to broadcast creation of soil texture.
100    CreateSoilTexture(Vec<AreaDto>),
101    /// An action used to broadcast deletion of soil texture.
102    DeleteSoilTexture(Vec<Uuid>),
103    /// An action used to broadcast change of soil texture.
104    UpdateSoilTexture(Vec<UpdateAreaActionPayload>),
105    /// An action used to update `add_date` of soil texture.
106    UpdateSoilTextureAddDate(Vec<UpdateAreaAddDateActionPayload>),
107    /// An action used to update `remove_date` of soil texture.
108    UpdateSoilTextureRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
109    /// An action used to update `notes` of soil texture.
110    UpdateSoilTextureNotes(Vec<UpdateAreaNotesActionPayload>),
111
112    /// An action used to broadcast creation of a baseLayerImage.
113    CreateBaseLayerImage(CreateBaseLayerImageActionPayload),
114    /// An action used to broadcast update of a baseLayerImage.
115    UpdateBaseLayerImage(UpdateBaseLayerImageActionPayload),
116    /// An action used to broadcast deletion of a baseLayerImage.
117    DeleteBaseLayerImage(DeleteBaseLayerImageActionPayload),
118    /// An action used to broadcast an update to the map geometry.
119    UpdateMapGeometry(UpdateMapGeometryActionPayload),
120    /// An action used to update `additional_name` of one planting.
121    UpdatePlantingAdditionalName(UpdatePlantingAdditionalNamePayload),
122
123    /// An action used to broadcast creation of new drawings.
124    CreateDrawing(Vec<DrawingDto>),
125    /// An action used to broadcast deletion of an existing drawings.
126    DeleteDrawing(Vec<Uuid>),
127    /// An action used to broadcast arbitrary updates of existing drawings.
128    UpdateDrawing(Vec<DrawingDto>),
129    /// An action used to broadcast the update of `add_date` of existing drawings.
130    UpdateDrawingAddDate(Vec<DrawingDto>),
131    /// An action used to broadcast the update of `remove_date` of existing drawings.
132    UpdateDrawingRemoveDate(Vec<DrawingDto>),
133    /// An action used to broadcast the update of `notes` of existing drawings.
134    UpdateDrawingNotes(Vec<UpdateDrawingNotesActionPayload>),
135
136    /// An action used to signal a server shutdown.
137    ServerShutdown(String),
138}
139
140impl Action {
141    #[must_use]
142    pub fn new_create_planting_action(
143        dtos: Vec<PlantingDto>,
144        user_id: Uuid,
145        action_id: Uuid,
146    ) -> Self {
147        Self {
148            action_id,
149            user_id,
150            action: ActionType::CreatePlanting(dtos),
151        }
152    }
153
154    #[must_use]
155    pub fn new_delete_planting_action(
156        dtos: &[DeletePlantingDto],
157        user_id: Uuid,
158        action_id: Uuid,
159    ) -> Self {
160        Self {
161            action_id,
162            user_id,
163            action: ActionType::DeletePlanting(
164                dtos.iter()
165                    .map(|dto| DeletePlantingActionPayload { id: dto.id })
166                    .collect(),
167            ),
168        }
169    }
170
171    #[must_use]
172    pub fn new_move_planting_action(
173        dtos: &[MovePlantingDto],
174        user_id: Uuid,
175        action_id: Uuid,
176    ) -> Self {
177        Self {
178            action_id,
179            user_id,
180            action: ActionType::MovePlanting(
181                dtos.iter()
182                    .map(|dto| MovePlantingActionPayload {
183                        id: dto.id,
184                        x: dto.x,
185                        y: dto.y,
186                    })
187                    .collect(),
188            ),
189        }
190    }
191
192    #[must_use]
193    pub fn new_transform_planting_action(
194        dtos: &[TransformPlantingDto],
195        user_id: Uuid,
196        action_id: Uuid,
197    ) -> Self {
198        Self {
199            action_id,
200            user_id,
201            action: ActionType::TransformPlanting(
202                dtos.iter()
203                    .map(|dto| TransformPlantingActionPayload {
204                        id: dto.id,
205                        x: dto.x,
206                        y: dto.y,
207                        rotation: dto.rotation,
208                        size_x: dto.size_x,
209                        size_y: dto.size_y,
210                        height: dto.height,
211                    })
212                    .collect(),
213            ),
214        }
215    }
216
217    #[must_use]
218    pub fn new_update_planting_add_date_action(
219        dtos: &[UpdateAddDatePlantingDto],
220        user_id: Uuid,
221        action_id: Uuid,
222    ) -> Self {
223        Self {
224            action_id,
225            user_id,
226            action: ActionType::UpdatePlantingAddDate(
227                dtos.iter()
228                    .map(|dto| UpdateAddDateActionPayload {
229                        id: dto.id,
230                        add_date: dto.add_date,
231                    })
232                    .collect(),
233            ),
234        }
235    }
236
237    #[must_use]
238    pub fn new_update_planting_remove_date_action(
239        dtos: &[UpdateRemoveDatePlantingDto],
240        user_id: Uuid,
241        action_id: Uuid,
242    ) -> Self {
243        Self {
244            action_id,
245            user_id,
246            action: ActionType::UpdatePlantingRemoveDate(
247                dtos.iter()
248                    .map(|dto| UpdateRemoveDateActionPayload {
249                        id: dto.id,
250                        remove_date: dto.remove_date,
251                    })
252                    .collect(),
253            ),
254        }
255    }
256
257    #[must_use]
258    pub fn new_update_planting_note_action(
259        dtos: &[UpdatePlantingNoteDto],
260        user_id: Uuid,
261        action_id: Uuid,
262    ) -> Self {
263        Self {
264            action_id,
265            user_id,
266            action: ActionType::UpdatePlantingNotes(
267                dtos.iter()
268                    .map(|dto| UpdatePlantingNotesActionPayload {
269                        id: dto.id,
270                        notes: dto.notes.clone(),
271                    })
272                    .collect(),
273            ),
274        }
275    }
276
277    #[must_use]
278    pub fn new_create_area_action(
279        area_kind: AreaKind,
280        dtos: Vec<AreaDto>,
281        user_id: Uuid,
282        action_id: Uuid,
283    ) -> Self {
284        Self {
285            action_id,
286            user_id,
287            action: match area_kind {
288                AreaKind::Shade => ActionType::CreateShading(dtos),
289                AreaKind::Hydrology => ActionType::CreateHydrology(dtos),
290                AreaKind::SoilTexture => ActionType::CreateSoilTexture(dtos),
291            },
292        }
293    }
294
295    #[must_use]
296    pub fn new_update_area_action(
297        area_kind: AreaKind,
298        dtos: &[AreaDto],
299        user_id: Uuid,
300        action_id: Uuid,
301    ) -> Self {
302        let payload = dtos
303            .iter()
304            .map(|dto| UpdateAreaActionPayload {
305                id: dto.id,
306                area_type: dto.area_type.clone(),
307            })
308            .collect();
309        Self {
310            action_id,
311            user_id,
312            action: match area_kind {
313                AreaKind::Shade => ActionType::UpdateShading(payload),
314                AreaKind::Hydrology => ActionType::UpdateHydrology(payload),
315                AreaKind::SoilTexture => ActionType::UpdateSoilTexture(payload),
316            },
317        }
318    }
319
320    #[must_use]
321    pub fn new_update_area_add_date_action(
322        area_kind: AreaKind,
323        dtos: &[AreaDto],
324        user_id: Uuid,
325        action_id: Uuid,
326    ) -> Self {
327        let payload = dtos
328            .iter()
329            .map(|dto| UpdateAreaAddDateActionPayload {
330                id: dto.id,
331                add_date: dto.add_date,
332            })
333            .collect();
334        Self {
335            action_id,
336            user_id,
337            action: match area_kind {
338                AreaKind::Shade => ActionType::UpdateShadingAddDate(payload),
339                AreaKind::Hydrology => ActionType::UpdateHydrologyAddDate(payload),
340                AreaKind::SoilTexture => ActionType::UpdateSoilTextureAddDate(payload),
341            },
342        }
343    }
344
345    #[must_use]
346    pub fn new_update_area_remove_date_action(
347        area_kind: AreaKind,
348        dtos: &[AreaDto],
349        user_id: Uuid,
350        action_id: Uuid,
351    ) -> Self {
352        let payload = dtos
353            .iter()
354            .map(|dto| UpdateAreaRemoveDateActionPayload {
355                id: dto.id,
356                remove_date: dto.remove_date,
357            })
358            .collect();
359        Self {
360            action_id,
361            user_id,
362            action: match area_kind {
363                AreaKind::Shade => ActionType::UpdateShadingRemoveDate(payload),
364                AreaKind::Hydrology => ActionType::UpdateHydrologyRemoveDate(payload),
365                AreaKind::SoilTexture => ActionType::UpdateSoilTextureRemoveDate(payload),
366            },
367        }
368    }
369
370    #[must_use]
371    pub fn new_update_area_notes_action(
372        area_kind: AreaKind,
373        dtos: &[AreaDto],
374        user_id: Uuid,
375        action_id: Uuid,
376    ) -> Self {
377        let payload: Vec<UpdateAreaNotesActionPayload> = dtos
378            .iter()
379            .map(|dto| UpdateAreaNotesActionPayload {
380                id: dto.id,
381                notes: dto.notes.clone(),
382            })
383            .collect();
384        Self {
385            action_id,
386            user_id,
387            action: match area_kind {
388                AreaKind::Shade => ActionType::UpdateShadingNotes(payload),
389                AreaKind::Hydrology => ActionType::UpdateHydrologyNotes(payload),
390                AreaKind::SoilTexture => ActionType::UpdateSoilTextureNotes(payload),
391            },
392        }
393    }
394
395    #[must_use]
396    pub fn new_delete_area_action(
397        area_kind: AreaKind,
398        ids: Vec<Uuid>,
399        user_id: Uuid,
400        action_id: Uuid,
401    ) -> Self {
402        Self {
403            action_id,
404            user_id,
405            action: match area_kind {
406                AreaKind::Shade => ActionType::DeleteShading(ids),
407                AreaKind::Hydrology => ActionType::DeleteHydrology(ids),
408                AreaKind::SoilTexture => ActionType::DeleteSoilTexture(ids),
409            },
410        }
411    }
412
413    #[must_use]
414    pub fn new_shutdown_signal_action(message: String) -> Self {
415        Self {
416            action_id: Uuid::now_v7(),
417            user_id: SYSTEM_USER_ID,
418            action: ActionType::ServerShutdown(message),
419        }
420    }
421}
422
423#[typeshare]
424#[derive(Debug, Serialize, Clone)]
425/// The payload of the [`ActionType::RestoreDrawingLayer`].
426#[serde(rename_all = "camelCase")]
427pub struct RestoreDrawingLayerActionPayload {
428    // ID of the layer
429    id: Uuid,
430    // Drawings saved on that layer
431    drawings: Vec<DrawingDto>,
432}
433
434impl RestoreDrawingLayerActionPayload {
435    #[must_use]
436    pub fn new(id: Uuid, drawings: Vec<DrawingDto>) -> Self {
437        Self { id, drawings }
438    }
439}
440
441#[typeshare]
442#[derive(Debug, Serialize, Clone)]
443/// The payload of the [`ActionType::CreatePlanting`].
444/// This struct should always match [`PlantingDto`].
445#[serde(rename_all = "camelCase")]
446pub struct CreatePlantActionPayload {
447    id: Uuid,
448    layer_id: Uuid,
449    plant_id: i32,
450    x: i32,
451    y: i32,
452    rotation: i32,
453    size_x: i32,
454    size_y: i32,
455    height: Option<i32>,
456    add_date: Option<NaiveDate>,
457    remove_date: Option<NaiveDate>,
458    seed_id: Option<i32>,
459    additional_name: Option<String>,
460    is_area: bool,
461}
462
463#[typeshare]
464#[derive(Debug, Serialize, Clone)]
465/// The payload of the [`ActionType::DeletePlanting`].
466#[serde(rename_all = "camelCase")]
467pub struct DeletePlantingActionPayload {
468    id: Uuid,
469}
470
471#[typeshare]
472#[derive(Debug, Serialize, Clone)]
473/// The payload of the [`ActionType::MovePlanting`].
474#[serde(rename_all = "camelCase")]
475pub struct MovePlantingActionPayload {
476    id: Uuid,
477    x: i32,
478    y: i32,
479}
480
481#[typeshare]
482#[derive(Debug, Serialize, Clone)]
483/// The payload of the [`ActionType::TransformPlanting`].
484#[serde(rename_all = "camelCase")]
485pub struct TransformPlantingActionPayload {
486    id: Uuid,
487    x: i32,
488    y: i32,
489    rotation: i32,
490    size_x: i32,
491    size_y: i32,
492    height: Option<i32>,
493}
494
495#[typeshare]
496#[derive(Debug, Serialize, Clone)]
497#[serde(rename_all = "camelCase")]
498pub struct CreateShadingActionPayload {
499    id: Uuid,
500    layer_id: Uuid,
501    area_type: AreaType,
502    geometry: Polygon<Point>,
503    add_date: Option<NaiveDate>,
504    remove_date: Option<NaiveDate>,
505    notes: String,
506}
507
508#[typeshare]
509#[derive(Debug, Serialize, Clone)]
510#[serde(rename_all = "camelCase")]
511pub struct CreateHydrologyActionPayload {
512    id: Uuid,
513    layer_id: Uuid,
514    area_type: AreaType,
515    geometry: Polygon<Point>,
516    add_date: Option<NaiveDate>,
517    remove_date: Option<NaiveDate>,
518    notes: String,
519}
520
521#[typeshare]
522#[derive(Debug, Serialize, Clone)]
523#[serde(rename_all = "camelCase")]
524pub struct CreateAreaActionPayload {
525    id: Uuid,
526    layer_id: Uuid,
527    area_type: AreaType,
528    geometry: Polygon<Point>,
529    add_date: Option<NaiveDate>,
530    remove_date: Option<NaiveDate>,
531    notes: String,
532}
533
534impl CreateAreaActionPayload {
535    #[must_use]
536    pub fn new(payload: AreaDto) -> Self {
537        Self {
538            id: payload.id,
539            layer_id: payload.layer_id,
540            area_type: payload.area_type,
541            geometry: payload.geometry,
542            add_date: payload.add_date,
543            remove_date: payload.remove_date,
544            notes: payload.notes,
545        }
546    }
547}
548
549#[typeshare]
550#[derive(Debug, Serialize, Clone)]
551/// The payload of [`ActionType::UpdateShading`, `ActionType::UpdateHydrology`, `ActionType::UpdateSoilTexture`].
552#[serde(rename_all = "camelCase")]
553pub struct UpdateAreaActionPayload {
554    id: Uuid,
555    area_type: AreaType,
556}
557
558impl UpdateAreaActionPayload {
559    #[must_use]
560    pub fn new(payload: AreaDto) -> Self {
561        Self {
562            id: payload.id,
563            area_type: payload.area_type,
564        }
565    }
566}
567
568#[typeshare]
569#[derive(Debug, Serialize, Clone)]
570/// The payload of the [`ActionType::UpdateShadingAddDate`, `ActionType::UpdateHydrologyAddDate`, `ActionType::UpdateSoilTextureAddDate`].
571#[serde(rename_all = "camelCase")]
572pub struct UpdateAreaAddDateActionPayload {
573    id: Uuid,
574    add_date: Option<NaiveDate>,
575}
576
577impl UpdateAreaAddDateActionPayload {
578    #[must_use]
579    pub fn new(payload: &AreaDto) -> Self {
580        Self {
581            id: payload.id,
582            add_date: payload.add_date,
583        }
584    }
585}
586
587#[typeshare]
588#[derive(Debug, Serialize, Clone)]
589/// The payload of the [`ActionType::UpdateShadingRemoveDate`, `ActionType::UpdateHydrologyRemoveDate`, `ActionType::UpdateSoilTextureRemoveDate`].
590#[serde(rename_all = "camelCase")]
591pub struct UpdateAreaRemoveDateActionPayload {
592    id: Uuid,
593    remove_date: Option<NaiveDate>,
594}
595
596impl UpdateAreaRemoveDateActionPayload {
597    #[must_use]
598    pub fn new(payload: &AreaDto) -> Self {
599        Self {
600            id: payload.id,
601            remove_date: payload.remove_date,
602        }
603    }
604}
605
606#[typeshare]
607#[derive(Debug, Serialize, Clone)]
608/// The payload of the [`ActionType::UpdateShadingNotes`, `ActionType::UpdateHydrologyNotes`, `ActionType::UpdateSoilTextureNotes`].
609pub struct UpdateAreaNotesActionPayload {
610    id: Uuid,
611    notes: String,
612}
613
614impl UpdateAreaNotesActionPayload {
615    #[must_use]
616    pub fn new(payload: &AreaDto) -> Self {
617        Self {
618            id: payload.id,
619            notes: payload.notes.clone(),
620        }
621    }
622}
623
624#[typeshare]
625#[derive(Debug, Serialize, Clone)]
626/// The payload of the [`ActionType::UpdatePlantingNotes`].
627#[serde(rename_all = "camelCase")]
628pub struct UpdatePlantingNotesActionPayload {
629    id: Uuid,
630    notes: String,
631}
632
633#[typeshare]
634#[derive(Debug, Serialize, Clone)]
635/// The payload of the [`ActionType::CreateBaseLayerImage`].
636/// This struct should always match [`BaseLayerImageDto`].
637#[serde(rename_all = "camelCase")]
638pub struct CreateBaseLayerImageActionPayload {
639    id: Uuid,
640    layer_id: Uuid,
641    rotation: i32,
642    scale: i32,
643    path: String,
644}
645
646impl CreateBaseLayerImageActionPayload {
647    #[must_use]
648    pub fn new(payload: BaseLayerImageDto) -> Self {
649        Self {
650            id: payload.id,
651            layer_id: payload.layer_id,
652            rotation: payload.rotation,
653            scale: payload.scale,
654            path: payload.path,
655        }
656    }
657}
658
659#[typeshare]
660#[derive(Debug, Serialize, Clone)]
661/// The payload of the [`ActionType::DeleteBaseLayerImage`].
662#[serde(rename_all = "camelCase")]
663pub struct DeleteBaseLayerImageActionPayload {
664    id: Uuid,
665}
666
667impl DeleteBaseLayerImageActionPayload {
668    #[must_use]
669    pub fn new(id: Uuid) -> Self {
670        Self { id }
671    }
672}
673
674#[typeshare]
675#[derive(Debug, Serialize, Clone)]
676/// The payload of the [`ActionType::UpdateBaseLayerImage`].
677#[serde(rename_all = "camelCase")]
678pub struct UpdateBaseLayerImageActionPayload {
679    id: Uuid,
680    layer_id: Uuid,
681    rotation: i32,
682    scale: i32,
683    path: String,
684    x: i32,
685    y: i32,
686}
687
688impl UpdateBaseLayerImageActionPayload {
689    #[must_use]
690    pub fn new(payload: BaseLayerImageDto) -> Self {
691        Self {
692            id: payload.id,
693            layer_id: payload.layer_id,
694            rotation: payload.rotation,
695            scale: payload.scale,
696            path: payload.path,
697            x: payload.x,
698            y: payload.y,
699        }
700    }
701}
702
703#[typeshare]
704#[derive(Debug, Serialize, Clone)]
705/// The payload of the actions [`ActionType::UpdatePlantingAddDate]`].
706#[serde(rename_all = "camelCase")]
707pub struct UpdateAddDateActionPayload {
708    id: Uuid,
709    add_date: Option<NaiveDate>,
710}
711
712#[typeshare]
713#[derive(Debug, Serialize, Clone)]
714/// The payload of the [`ActionType::UpdatePlantingRemoveDate`].
715#[serde(rename_all = "camelCase")]
716pub struct UpdateRemoveDateActionPayload {
717    id: Uuid,
718    remove_date: Option<NaiveDate>,
719}
720
721#[typeshare]
722#[derive(Debug, Serialize, Clone)]
723/// The payload of the [`ActionType::UpdateMapGeometry`].
724#[serde(rename_all = "camelCase")]
725pub struct UpdateMapGeometryActionPayload {
726    /// The entity id for this action.
727    map_id: i32,
728    // E.g. `{"rings": [[{"x": 0.0,"y": 0.0},{"x": 1000.0,"y": 0.0},{"x": 1000.0,"y": 1000.0},{"x": 0.0,"y": 1000.0},{"x": 0.0,"y": 0.0}]],"srid": 4326}`
729    #[typeshare(serialized_as = "object")]
730    geometry: Polygon<Point>,
731}
732
733impl UpdateMapGeometryActionPayload {
734    #[must_use]
735    pub fn new(payload: UpdateMapGeometryDto, map_id: i32) -> Self {
736        Self {
737            map_id,
738            geometry: payload.geometry,
739        }
740    }
741}
742
743#[typeshare]
744#[derive(Debug, Serialize, Clone)]
745/// The payload of the [`ActionType::UpdatePlantingRemoveDate`].
746#[serde(rename_all = "camelCase")]
747pub struct UpdatePlantingAdditionalNamePayload {
748    id: Uuid,
749    additional_name: Option<String>,
750}
751
752impl UpdatePlantingAdditionalNamePayload {
753    #[must_use]
754    pub fn new(payload: &PlantingDto, new_additional_name: Option<String>) -> Self {
755        Self {
756            id: payload.id,
757            additional_name: new_additional_name,
758        }
759    }
760}
761
762#[typeshare]
763#[derive(Debug, Serialize, Clone)]
764/// The payload of the [`ActionType::UpdatePlantingNotes`].
765#[serde(rename_all = "camelCase")]
766pub struct UpdateDrawingNotesActionPayload {
767    id: Uuid,
768    notes: String,
769}
770
771impl UpdateDrawingNotesActionPayload {
772    #[must_use]
773    pub fn new(drawing: DrawingDto) -> Self {
774        Self {
775            id: drawing.id,
776            notes: drawing.notes,
777        }
778    }
779}