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
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// Use the name of the enum variant as the type field looking like { "type": "CreatePlanting", ... }.
40/// An enum representing all the actions that can be broadcasted via [`crate::sse::broadcaster::Broadcaster`].
41#[serde(tag = "type", content = "payload")]
42pub enum ActionType {
43    /// An action used to broadcast creation of a layer.
44    CreateLayer(LayerDto),
45    /// An action used to broadcast soft-deletion of a layer.
46    /// Deleted layers can be restored.
47    DeleteLayer(Uuid),
48    /// An action used to broadcast restoration of a deleted layer.
49    /// Restore is only supported for drawing layers
50    RestoreDrawingLayer(RestoreDrawingLayerActionPayload),
51    /// An action used to broadcast the renaming of a layer.
52    RenameLayer(LayerRenameDto),
53    /// An action used to broadcast the reordering of multiple layers.
54    ReorderLayers(Vec<Uuid>),
55
56    /// An action used to broadcast creation of plantings.
57    CreatePlanting(Vec<PlantingDto>),
58    /// An action used to broadcast deletion of plantings.
59    DeletePlanting(Vec<DeletePlantingActionPayload>),
60    /// An action used to broadcast movement of plantings.
61    MovePlanting(Vec<MovePlantingActionPayload>),
62    /// An action used to broadcast transformation of plantings.
63    TransformPlanting(Vec<TransformPlantingActionPayload>),
64    /// An action used to update the `add_date` of plantings.
65    UpdatePlantingAddDate(Vec<UpdateAddDateActionPayload>),
66    /// An action used to update the `remove_date` of plantings.
67    UpdatePlantingRemoveDate(Vec<UpdateRemoveDateActionPayload>),
68    /// An action used to broadcast updating Markdown notes of plantings.
69    UpdatePlantingNotes(Vec<UpdatePlantingNotesActionPayload>),
70
71    /// An action used to broadcast creation of shading.
72    CreateShading(Vec<AreaDto>),
73    /// An action used to broadcast deletion of shading.
74    DeleteShading(Vec<Uuid>),
75    /// An action used to broadcast change of shading.
76    UpdateShading(Vec<UpdateAreaActionPayload>),
77    /// An action used to update `add_date` of shading.
78    UpdateShadingAddDate(Vec<UpdateAreaAddDateActionPayload>),
79    /// An action used to update `remove_date` of shading.
80    UpdateShadingRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
81    /// An action used to update `notes` of shading.
82    UpdateShadingNotes(Vec<UpdateAreaNotesActionPayload>),
83
84    /// An action used to broadcast creation of hydrology.
85    CreateHydrology(Vec<AreaDto>),
86    /// An action used to broadcast deletion of hydrology.
87    DeleteHydrology(Vec<Uuid>),
88    /// An action used to broadcast change of hydrology.
89    UpdateHydrology(Vec<UpdateAreaActionPayload>),
90    /// An action used to update `add_date` of hydrology.
91    UpdateHydrologyAddDate(Vec<UpdateAreaAddDateActionPayload>),
92    /// An action used to update `remove_date` of hydrology.
93    UpdateHydrologyRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
94    /// An action used to update `notes` of hydrology.
95    UpdateHydrologyNotes(Vec<UpdateAreaNotesActionPayload>),
96
97    /// An action used to broadcast creation of soil texture.
98    CreateSoilTexture(Vec<AreaDto>),
99    /// An action used to broadcast deletion of soil texture.
100    DeleteSoilTexture(Vec<Uuid>),
101    /// An action used to broadcast change of soil texture.
102    UpdateSoilTexture(Vec<UpdateAreaActionPayload>),
103    /// An action used to update `add_date` of soil texture.
104    UpdateSoilTextureAddDate(Vec<UpdateAreaAddDateActionPayload>),
105    /// An action used to update `remove_date` of soil texture.
106    UpdateSoilTextureRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
107    /// An action used to update `notes` of soil texture.
108    UpdateSoilTextureNotes(Vec<UpdateAreaNotesActionPayload>),
109
110    /// An action used to broadcast creation of a baseLayerImage.
111    CreateBaseLayerImage(CreateBaseLayerImageActionPayload),
112    /// An action used to broadcast update of a baseLayerImage.
113    UpdateBaseLayerImage(UpdateBaseLayerImageActionPayload),
114    /// An action used to broadcast deletion of a baseLayerImage.
115    DeleteBaseLayerImage(DeleteBaseLayerImageActionPayload),
116    /// An action used to broadcast an update to the map geometry.
117    UpdateMapGeometry(UpdateMapGeometryActionPayload),
118    /// An action used to update `additional_name` of one planting.
119    UpdatePlantingAdditionalName(UpdatePlantingAdditionalNamePayload),
120
121    /// An action used to broadcast creation of new drawings.
122    CreateDrawing(Vec<DrawingDto>),
123    /// An action used to broadcast deletion of an existing drawings.
124    DeleteDrawing(Vec<Uuid>),
125    /// An action used to broadcast arbitrary updates of existing drawings.
126    UpdateDrawing(Vec<DrawingDto>),
127    /// An action used to broadcast the update of `add_date` of existing drawings.
128    UpdateDrawingAddDate(Vec<DrawingDto>),
129    /// An action used to broadcast the update of `remove_date` of existing drawings.
130    UpdateDrawingRemoveDate(Vec<DrawingDto>),
131    /// An action used to broadcast the update of `notes` of existing drawings.
132    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/// The payload of the [`ActionType::RestoreDrawingLayer`].
412#[serde(rename_all = "camelCase")]
413pub struct RestoreDrawingLayerActionPayload {
414    // ID of the layer
415    id: Uuid,
416    // Drawings saved on that layer
417    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/// The payload of the [`ActionType::CreatePlanting`].
430/// This struct should always match [`PlantingDto`].
431#[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/// The payload of the [`ActionType::DeletePlanting`].
452#[serde(rename_all = "camelCase")]
453pub struct DeletePlantingActionPayload {
454    id: Uuid,
455}
456
457#[typeshare]
458#[derive(Debug, Serialize, Clone)]
459/// The payload of the [`ActionType::MovePlanting`].
460#[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/// The payload of the [`ActionType::TransformPlanting`].
470#[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/// The payload of [`ActionType::UpdateShading`, `ActionType::UpdateHydrology`, `ActionType::UpdateSoilTexture`].
538#[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/// The payload of the [`ActionType::UpdateShadingAddDate`, `ActionType::UpdateHydrologyAddDate`, `ActionType::UpdateSoilTextureAddDate`].
557#[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/// The payload of the [`ActionType::UpdateShadingRemoveDate`, `ActionType::UpdateHydrologyRemoveDate`, `ActionType::UpdateSoilTextureRemoveDate`].
576#[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)]
594/// The payload of the [`ActionType::UpdateShadingNotes`, `ActionType::UpdateHydrologyNotes`, `ActionType::UpdateSoilTextureNotes`].
595pub 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/// The payload of the [`ActionType::UpdatePlantingNotes`].
613#[serde(rename_all = "camelCase")]
614pub struct UpdatePlantingNotesActionPayload {
615    id: Uuid,
616    notes: String,
617}
618
619#[typeshare]
620#[derive(Debug, Serialize, Clone)]
621/// The payload of the [`ActionType::CreateBaseLayerImage`].
622/// This struct should always match [`BaseLayerImageDto`].
623#[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/// The payload of the [`ActionType::DeleteBaseLayerImage`].
648#[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/// The payload of the [`ActionType::UpdateBaseLayerImage`].
663#[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/// The payload of the actions [`ActionType::UpdatePlantingAddDate]`].
692#[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/// The payload of the [`ActionType::UpdatePlantingRemoveDate`].
701#[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/// The payload of the [`ActionType::UpdateMapGeometry`].
710#[serde(rename_all = "camelCase")]
711pub struct UpdateMapGeometryActionPayload {
712    /// The entity id for this action.
713    map_id: i32,
714    // 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}`
715    #[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/// The payload of the [`ActionType::UpdatePlantingRemoveDate`].
732#[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/// The payload of the [`ActionType::UpdatePlantingNotes`].
751#[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}