feat: edit and deletion of areas

This commit is contained in:
Max Hohlfeld 2024-11-01 15:56:07 +01:00
parent 03c47927e5
commit d0e8f48328
7 changed files with 94 additions and 11 deletions

View File

@ -0,0 +1,27 @@
use actix_web::{web, HttpResponse, Responder};
use sqlx::PgPool;
use crate::{
endpoints::IdPath,
models::{Area, Role, User},
utils::ApplicationError,
};
#[actix_web::delete("/area/delete/{id}")]
pub async fn delete(
user: web::ReqData<User>,
pool: web::Data<PgPool>,
path: web::Path<IdPath>,
) -> Result<impl Responder, ApplicationError> {
if user.role != Role::Admin {
return Err(ApplicationError::Unauthorized);
}
if Area::read_by_id(pool.get_ref(), path.id).await?.is_none() {
return Ok(HttpResponse::NotFound().finish());
};
Area::delete(pool.get_ref(), path.id).await?;
return Ok(HttpResponse::Ok().finish());
}

View File

@ -1,8 +1,11 @@
pub mod get_new; pub mod get_new;
pub mod post_new; pub mod post_new;
pub mod get_edit; pub mod get_edit;
pub mod post_edit;
pub mod delete;
use askama::Template; use askama::Template;
use serde::Deserialize;
use crate::models::{Area, Role, User}; use crate::models::{Area, Role, User};
@ -12,3 +15,8 @@ struct NewOrEditAreaTemplate {
user: User, user: User,
area: Option<Area>, area: Option<Area>,
} }
#[derive(Deserialize)]
struct AreaForm {
name: String,
}

View File

@ -0,0 +1,35 @@
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
use sqlx::PgPool;
use crate::{
endpoints::IdPath,
models::{Area, Role, User},
utils::ApplicationError,
};
use super::AreaForm;
#[actix_web::post("/area/edit/{id}")]
pub async fn post(
user: web::ReqData<User>,
pool: web::Data<PgPool>,
form: web::Form<AreaForm>,
path: web::Path<IdPath>,
) -> Result<impl Responder, ApplicationError> {
if user.role != Role::Admin {
return Err(ApplicationError::Unauthorized);
}
if let Some(area) = Area::read_by_id(pool.get_ref(), path.id).await? {
if area.name != form.name {
Area::update(pool.get_ref(), path.id, &form.name).await?;
}
return Ok(HttpResponse::Found()
.insert_header((LOCATION, "/locations"))
.insert_header(("HX-LOCATION", "/locations"))
.finish());
} else {
return Ok(HttpResponse::NotFound().finish());
}
}

View File

@ -1,19 +1,13 @@
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
use serde::Deserialize;
use sqlx::PgPool; use sqlx::PgPool;
use crate::models::{Area, Role, User}; use crate::{endpoints::area::AreaForm, models::{Area, Role, User}};
#[derive(Deserialize)]
struct NewAreaForm {
name: String,
}
#[actix_web::post("/area/new")] #[actix_web::post("/area/new")]
pub async fn post( pub async fn post(
user: web::ReqData<User>, user: web::ReqData<User>,
pool: web::Data<PgPool>, pool: web::Data<PgPool>,
form: web::Form<NewAreaForm>, form: web::Form<AreaForm>,
) -> impl Responder { ) -> impl Responder {
if user.role != Role::Admin { if user.role != Role::Admin {
return HttpResponse::Unauthorized().finish(); return HttpResponse::Unauthorized().finish();

View File

@ -60,6 +60,8 @@ pub fn init(cfg: &mut ServiceConfig) {
cfg.service(area::get_new::get); cfg.service(area::get_new::get);
cfg.service(area::post_new::post); cfg.service(area::post_new::post);
cfg.service(area::get_edit::get); cfg.service(area::get_edit::get);
cfg.service(area::post_edit::post);
cfg.service(area::delete::delete);
cfg.service(export::get_availability::get); cfg.service(export::get_availability::get);
cfg.service(export::get_availability_data::get); cfg.service(export::get_availability_data::get);

View File

@ -25,10 +25,26 @@ impl Area {
} }
pub async fn read_all(pool: &PgPool) -> Result<Vec<Area>> { pub async fn read_all(pool: &PgPool) -> Result<Vec<Area>> {
let records = query_as!(Area, "SELECT * FROM area") let records = query_as!(Area, "SELECT * FROM area ORDER by id")
.fetch_all(pool) .fetch_all(pool)
.await?; .await?;
Ok(records) Ok(records)
} }
pub async fn update(pool: &PgPool, id: i32, name: &str) -> Result<()> {
query!("UPDATE area SET name = $1 WHERE id = $2;", name, id)
.execute(pool)
.await?;
Ok(())
}
pub async fn delete(pool: &PgPool, id: i32) -> Result<()> {
sqlx::query!("DELETE FROM area WHERE id = $1;", id)
.execute(pool)
.await?;
Ok(())
}
} }

View File

@ -46,11 +46,12 @@
<use href="/static/feather-sprite.svg#edit" /> <use href="/static/feather-sprite.svg#edit" />
</svg> </svg>
</a> </a>
<a class="button is-danger is-light" hx-boost="true" href="/area/delete/{{ gl.0.id }}"> <button class="button is-danger is-light" hx-delete="/area/delete/{{ gl.0.id }}" hx-swap="delete"
hx-target="closest .box" hx-trigger="confirmed">
<svg class="icon"> <svg class="icon">
<use href="/static/feather-sprite.svg#x-circle" /> <use href="/static/feather-sprite.svg#x-circle" />
</svg> </svg>
</a> </button>
</div> </div>
</div> </div>
</div> </div>