#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::missing_const_for_fn)]
use chrono::NaiveDate;
use postgis_diesel::types::{Point, Polygon};
use serde::Serialize;
use typeshare::typeshare;
use uuid::Uuid;
use crate::model::dto::{
areas::{AreaDto, AreaKind, AreaType},
base_layer_images::BaseLayerImageDto,
drawings::DrawingDto,
layers::{LayerDto, LayerRenameDto},
plantings::{
DeletePlantingDto, MovePlantingDto, PlantingDto, TransformPlantingDto,
UpdateAddDatePlantingDto, UpdatePlantingNoteDto, UpdateRemoveDatePlantingDto,
},
UpdateMapGeometryDto,
};
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Action {
pub action_id: Uuid,
pub user_id: Uuid,
pub action: ActionType,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(tag = "type", content = "payload")]
pub enum ActionType {
CreateLayer(LayerDto),
DeleteLayer(Uuid),
RestoreDrawingLayer(RestoreDrawingLayerActionPayload),
RenameLayer(LayerRenameDto),
ReorderLayers(Vec<Uuid>),
CreatePlanting(Vec<PlantingDto>),
DeletePlanting(Vec<DeletePlantingActionPayload>),
MovePlanting(Vec<MovePlantingActionPayload>),
TransformPlanting(Vec<TransformPlantingActionPayload>),
UpdatePlantingAddDate(Vec<UpdateAddDateActionPayload>),
UpdatePlantingRemoveDate(Vec<UpdateRemoveDateActionPayload>),
UpdatePlantingNotes(Vec<UpdatePlantingNotesActionPayload>),
CreateShading(Vec<AreaDto>),
DeleteShading(Vec<Uuid>),
UpdateShading(Vec<UpdateAreaActionPayload>),
UpdateShadingAddDate(Vec<UpdateAreaAddDateActionPayload>),
UpdateShadingRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
UpdateShadingNotes(Vec<UpdateAreaNotesActionPayload>),
CreateHydrology(Vec<AreaDto>),
DeleteHydrology(Vec<Uuid>),
UpdateHydrology(Vec<UpdateAreaActionPayload>),
UpdateHydrologyAddDate(Vec<UpdateAreaAddDateActionPayload>),
UpdateHydrologyRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
UpdateHydrologyNotes(Vec<UpdateAreaNotesActionPayload>),
CreateSoilTexture(Vec<AreaDto>),
DeleteSoilTexture(Vec<Uuid>),
UpdateSoilTexture(Vec<UpdateAreaActionPayload>),
UpdateSoilTextureAddDate(Vec<UpdateAreaAddDateActionPayload>),
UpdateSoilTextureRemoveDate(Vec<UpdateAreaRemoveDateActionPayload>),
UpdateSoilTextureNotes(Vec<UpdateAreaNotesActionPayload>),
CreateBaseLayerImage(CreateBaseLayerImageActionPayload),
UpdateBaseLayerImage(UpdateBaseLayerImageActionPayload),
DeleteBaseLayerImage(DeleteBaseLayerImageActionPayload),
UpdateMapGeometry(UpdateMapGeometryActionPayload),
UpdatePlantingAdditionalName(UpdatePlantingAdditionalNamePayload),
CreateDrawing(Vec<DrawingDto>),
DeleteDrawing(Vec<Uuid>),
UpdateDrawing(Vec<DrawingDto>),
UpdateDrawingAddDate(Vec<DrawingDto>),
UpdateDrawingRemoveDate(Vec<DrawingDto>),
UpdateDrawingNotes(Vec<UpdateDrawingNotesActionPayload>),
}
impl Action {
#[must_use]
pub fn new_create_planting_action(
dtos: Vec<PlantingDto>,
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::CreatePlanting(dtos),
}
}
#[must_use]
pub fn new_delete_planting_action(
dtos: &[DeletePlantingDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::DeletePlanting(
dtos.iter()
.map(|dto| DeletePlantingActionPayload { id: dto.id })
.collect(),
),
}
}
#[must_use]
pub fn new_move_planting_action(
dtos: &[MovePlantingDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::MovePlanting(
dtos.iter()
.map(|dto| MovePlantingActionPayload {
id: dto.id,
x: dto.x,
y: dto.y,
})
.collect(),
),
}
}
#[must_use]
pub fn new_transform_planting_action(
dtos: &[TransformPlantingDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::TransformPlanting(
dtos.iter()
.map(|dto| TransformPlantingActionPayload {
id: dto.id,
x: dto.x,
y: dto.y,
rotation: dto.rotation,
size_x: dto.size_x,
size_y: dto.size_y,
height: dto.height,
})
.collect(),
),
}
}
#[must_use]
pub fn new_update_planting_add_date_action(
dtos: &[UpdateAddDatePlantingDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::UpdatePlantingAddDate(
dtos.iter()
.map(|dto| UpdateAddDateActionPayload {
id: dto.id,
add_date: dto.add_date,
})
.collect(),
),
}
}
#[must_use]
pub fn new_update_planting_remove_date_action(
dtos: &[UpdateRemoveDatePlantingDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::UpdatePlantingRemoveDate(
dtos.iter()
.map(|dto| UpdateRemoveDateActionPayload {
id: dto.id,
remove_date: dto.remove_date,
})
.collect(),
),
}
}
#[must_use]
pub fn new_update_planting_note_action(
dtos: &[UpdatePlantingNoteDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: ActionType::UpdatePlantingNotes(
dtos.iter()
.map(|dto| UpdatePlantingNotesActionPayload {
id: dto.id,
notes: dto.notes.clone(),
})
.collect(),
),
}
}
#[must_use]
pub fn new_create_area_action(
area_kind: AreaKind,
dtos: Vec<AreaDto>,
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: match area_kind {
AreaKind::Shade => ActionType::CreateShading(dtos),
AreaKind::Hydrology => ActionType::CreateHydrology(dtos),
AreaKind::SoilTexture => ActionType::CreateSoilTexture(dtos),
},
}
}
#[must_use]
pub fn new_update_area_action(
area_kind: AreaKind,
dtos: &[AreaDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
let payload = dtos
.iter()
.map(|dto| UpdateAreaActionPayload {
id: dto.id,
area_type: dto.area_type.clone(),
})
.collect();
Self {
action_id,
user_id,
action: match area_kind {
AreaKind::Shade => ActionType::UpdateShading(payload),
AreaKind::Hydrology => ActionType::UpdateHydrology(payload),
AreaKind::SoilTexture => ActionType::UpdateSoilTexture(payload),
},
}
}
#[must_use]
pub fn new_update_area_add_date_action(
area_kind: AreaKind,
dtos: &[AreaDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
let payload = dtos
.iter()
.map(|dto| UpdateAreaAddDateActionPayload {
id: dto.id,
add_date: dto.add_date,
})
.collect();
Self {
action_id,
user_id,
action: match area_kind {
AreaKind::Shade => ActionType::UpdateShadingAddDate(payload),
AreaKind::Hydrology => ActionType::UpdateHydrologyAddDate(payload),
AreaKind::SoilTexture => ActionType::UpdateSoilTextureAddDate(payload),
},
}
}
#[must_use]
pub fn new_update_area_remove_date_action(
area_kind: AreaKind,
dtos: &[AreaDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
let payload = dtos
.iter()
.map(|dto| UpdateAreaRemoveDateActionPayload {
id: dto.id,
remove_date: dto.remove_date,
})
.collect();
Self {
action_id,
user_id,
action: match area_kind {
AreaKind::Shade => ActionType::UpdateShadingRemoveDate(payload),
AreaKind::Hydrology => ActionType::UpdateHydrologyRemoveDate(payload),
AreaKind::SoilTexture => ActionType::UpdateSoilTextureRemoveDate(payload),
},
}
}
#[must_use]
pub fn new_update_area_notes_action(
area_kind: AreaKind,
dtos: &[AreaDto],
user_id: Uuid,
action_id: Uuid,
) -> Self {
let payload: Vec<UpdateAreaNotesActionPayload> = dtos
.iter()
.map(|dto| UpdateAreaNotesActionPayload {
id: dto.id,
notes: dto.notes.clone(),
})
.collect();
Self {
action_id,
user_id,
action: match area_kind {
AreaKind::Shade => ActionType::UpdateShadingNotes(payload),
AreaKind::Hydrology => ActionType::UpdateHydrologyNotes(payload),
AreaKind::SoilTexture => ActionType::UpdateSoilTextureNotes(payload),
},
}
}
#[must_use]
pub fn new_delete_area_action(
area_kind: AreaKind,
ids: Vec<Uuid>,
user_id: Uuid,
action_id: Uuid,
) -> Self {
Self {
action_id,
user_id,
action: match area_kind {
AreaKind::Shade => ActionType::DeleteShading(ids),
AreaKind::Hydrology => ActionType::DeleteHydrology(ids),
AreaKind::SoilTexture => ActionType::DeleteSoilTexture(ids),
},
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct RestoreDrawingLayerActionPayload {
id: Uuid,
drawings: Vec<DrawingDto>,
}
impl RestoreDrawingLayerActionPayload {
#[must_use]
pub fn new(id: Uuid, drawings: Vec<DrawingDto>) -> Self {
Self { id, drawings }
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CreatePlantActionPayload {
id: Uuid,
layer_id: Uuid,
plant_id: i32,
x: i32,
y: i32,
rotation: f32,
size_x: i32,
size_y: i32,
height: Option<i32>,
add_date: Option<NaiveDate>,
remove_date: Option<NaiveDate>,
seed_id: Option<i32>,
additional_name: Option<String>,
is_area: bool,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DeletePlantingActionPayload {
id: Uuid,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct MovePlantingActionPayload {
id: Uuid,
x: i32,
y: i32,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct TransformPlantingActionPayload {
id: Uuid,
x: i32,
y: i32,
rotation: f32,
size_x: i32,
size_y: i32,
height: Option<i32>,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CreateShadingActionPayload {
id: Uuid,
layer_id: Uuid,
area_type: AreaType,
geometry: Polygon<Point>,
add_date: Option<NaiveDate>,
remove_date: Option<NaiveDate>,
notes: String,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CreateHydrologyActionPayload {
id: Uuid,
layer_id: Uuid,
area_type: AreaType,
geometry: Polygon<Point>,
add_date: Option<NaiveDate>,
remove_date: Option<NaiveDate>,
notes: String,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CreateAreaActionPayload {
id: Uuid,
layer_id: Uuid,
area_type: AreaType,
geometry: Polygon<Point>,
add_date: Option<NaiveDate>,
remove_date: Option<NaiveDate>,
notes: String,
}
impl CreateAreaActionPayload {
#[must_use]
pub fn new(payload: AreaDto) -> Self {
Self {
id: payload.id,
layer_id: payload.layer_id,
area_type: payload.area_type,
geometry: payload.geometry,
add_date: payload.add_date,
remove_date: payload.remove_date,
notes: payload.notes,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAreaActionPayload {
id: Uuid,
area_type: AreaType,
}
impl UpdateAreaActionPayload {
#[must_use]
pub fn new(payload: AreaDto) -> Self {
Self {
id: payload.id,
area_type: payload.area_type,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAreaAddDateActionPayload {
id: Uuid,
add_date: Option<NaiveDate>,
}
impl UpdateAreaAddDateActionPayload {
#[must_use]
pub fn new(payload: &AreaDto) -> Self {
Self {
id: payload.id,
add_date: payload.add_date,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAreaRemoveDateActionPayload {
id: Uuid,
remove_date: Option<NaiveDate>,
}
impl UpdateAreaRemoveDateActionPayload {
#[must_use]
pub fn new(payload: &AreaDto) -> Self {
Self {
id: payload.id,
remove_date: payload.remove_date,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
pub struct UpdateAreaNotesActionPayload {
id: Uuid,
notes: String,
}
impl UpdateAreaNotesActionPayload {
#[must_use]
pub fn new(payload: &AreaDto) -> Self {
Self {
id: payload.id,
notes: payload.notes.clone(),
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdatePlantingNotesActionPayload {
id: Uuid,
notes: String,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CreateBaseLayerImageActionPayload {
id: Uuid,
layer_id: Uuid,
rotation: f32,
scale: f32,
path: String,
}
impl CreateBaseLayerImageActionPayload {
#[must_use]
pub fn new(payload: BaseLayerImageDto) -> Self {
Self {
id: payload.id,
layer_id: payload.layer_id,
rotation: payload.rotation,
scale: payload.scale,
path: payload.path,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DeleteBaseLayerImageActionPayload {
id: Uuid,
}
impl DeleteBaseLayerImageActionPayload {
#[must_use]
pub fn new(id: Uuid) -> Self {
Self { id }
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateBaseLayerImageActionPayload {
id: Uuid,
layer_id: Uuid,
rotation: f32,
scale: f32,
path: String,
x: i32,
y: i32,
}
impl UpdateBaseLayerImageActionPayload {
#[must_use]
pub fn new(payload: BaseLayerImageDto) -> Self {
Self {
id: payload.id,
layer_id: payload.layer_id,
rotation: payload.rotation,
scale: payload.scale,
path: payload.path,
x: payload.x,
y: payload.y,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateAddDateActionPayload {
id: Uuid,
add_date: Option<NaiveDate>,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateRemoveDateActionPayload {
id: Uuid,
remove_date: Option<NaiveDate>,
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateMapGeometryActionPayload {
map_id: i32,
#[typeshare(serialized_as = "object")]
geometry: Polygon<Point>,
}
impl UpdateMapGeometryActionPayload {
#[must_use]
pub fn new(payload: UpdateMapGeometryDto, map_id: i32) -> Self {
Self {
map_id,
geometry: payload.geometry,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdatePlantingAdditionalNamePayload {
id: Uuid,
additional_name: Option<String>,
}
impl UpdatePlantingAdditionalNamePayload {
#[must_use]
pub fn new(payload: &PlantingDto, new_additional_name: Option<String>) -> Self {
Self {
id: payload.id,
additional_name: new_additional_name,
}
}
}
#[typeshare]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UpdateDrawingNotesActionPayload {
id: Uuid,
notes: String,
}
impl UpdateDrawingNotesActionPayload {
#[must_use]
pub fn new(drawing: DrawingDto) -> Self {
Self {
id: drawing.id,
notes: drawing.notes,
}
}
}