use actix_web::{
delete, get, patch, post,
web::{Json, Path, Query},
HttpResponse, Result,
};
use uuid::Uuid;
use crate::{
config::{
auth::user_info::UserInfo,
data::{SharedBroadcaster, SharedPool},
},
model::dto::{
actions::Action,
areas::{AreaKind, AreaSearchParameters, AreaUpdate, NewAreaDto, UpdateAreaDto},
core::ActionDtoWrapper,
},
service::areas,
};
#[utoipa::path(
context_path = "/api/maps/{map_id}/areas",
params(
("map_id" = i32, Path, description = "The id of the map the layer is on"),
AreaSearchParameters
),
responses(
(status = 200, description = "Find areas", body = Vec<AreaDto>),
),
security(
("oauth2" = [])
)
)]
#[get("")]
pub async fn find(
search_params: Query<AreaSearchParameters>,
pool: SharedPool,
) -> Result<HttpResponse> {
let response = areas::find(search_params.into_inner(), &pool).await?;
Ok(HttpResponse::Ok().json(response))
}
#[utoipa::path(
context_path = "/api/maps/{map_id}/areas",
params(
("map_id" = i32, Path, description = "The id of the map the layer is on"),
("area_kind" = AreaKind, Path, description = "The type of area"),
),
request_body = NewAreaDto,
responses(
(status = 201, description = "Create an areas", body = AreaDto)
),
security(
("oauth2" = [])
)
)]
#[post("/{area_kind}")]
pub async fn create(
path: Path<(i32, AreaKind)>,
new_areas: Json<ActionDtoWrapper<Vec<NewAreaDto>>>,
pool: SharedPool,
broadcaster: SharedBroadcaster,
user_info: UserInfo,
) -> Result<HttpResponse> {
let (map_id, area_kind) = path.into_inner();
let ActionDtoWrapper { action_id, dto } = new_areas.into_inner();
let created_areas = areas::create(area_kind, dto, &pool).await?;
broadcaster
.broadcast(
map_id,
Action::new_create_area_action(
area_kind,
created_areas.clone(),
user_info.id,
action_id,
),
)
.await;
Ok(HttpResponse::Created().json(created_areas))
}
#[utoipa::path(
context_path = "/api/maps/{map_id}/areas",
params(
("map_id" = i32, Path, description = "The id of the map the layer is on"),
("area_kind" = AreaKind, Path, description = "The type of area"),
),
request_body = ActionDtoWrapperUpdateAreas,
responses(
(status = 200, description = "Update multiple areas of the same kind", body = Vec<AreaDto>)
),
security(
("oauth2" = [])
)
)]
#[patch("/{area_kind}")]
pub async fn update(
path: Path<(i32, AreaKind)>,
update_areas: Json<ActionDtoWrapper<UpdateAreaDto>>,
pool: SharedPool,
broadcaster: SharedBroadcaster,
user_info: UserInfo,
) -> Result<HttpResponse> {
let (map_id, area_kind) = path.into_inner();
let ActionDtoWrapper { action_id, dto } = update_areas.into_inner();
let updated = areas::update(area_kind, dto.clone(), &pool).await?;
let user_id = user_info.id;
let action = match dto.update {
AreaUpdate::UpdateValue(_) => {
Action::new_update_area_action(area_kind, &updated, user_id, action_id)
}
AreaUpdate::UpdateAddDate(_) => {
Action::new_update_area_add_date_action(area_kind, &updated, user_id, action_id)
}
AreaUpdate::UpdateRemoveDate(_) => {
Action::new_update_area_remove_date_action(area_kind, &updated, user_id, action_id)
}
AreaUpdate::UpdateNotes(_) => {
Action::new_update_area_notes_action(area_kind, &updated, user_id, action_id)
}
};
broadcaster.broadcast(map_id, action).await;
Ok(HttpResponse::Ok().json(updated))
}
#[utoipa::path(
context_path = "/api/maps/{map_id}/areas",
params(
("map_id" = i32, Path, description = "The id of the map the layer is on"),
("area_kind" = AreaKind, Path, description = "The type of area"),
),
request_body = ActionDtoWrapperDeleteAreas,
responses(
(status = 200, description = "Areas deleted")
),
security(
("oauth2" = [])
)
)]
#[delete("/{area_kind}")]
pub async fn delete(
path: Path<(i32, AreaKind)>,
ids: Json<ActionDtoWrapper<Vec<Uuid>>>,
pool: SharedPool,
broadcaster: SharedBroadcaster,
user_info: UserInfo,
) -> Result<HttpResponse> {
let (map_id, area_kind) = path.into_inner();
let ActionDtoWrapper { action_id, dto } = ids.into_inner();
areas::delete_by_ids(area_kind, dto.clone(), &pool).await?;
broadcaster
.broadcast(
map_id,
Action::new_delete_area_action(area_kind, dto, user_info.id, action_id),
)
.await;
Ok(HttpResponse::Ok().finish())
}