feat: wip edit of area
This commit is contained in:
parent
bbc23c39a8
commit
e515057e14
31
src/endpoints/area/get_edit.rs
Normal file
31
src/endpoints/area/get_edit.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
endpoints::{area::NewOrEditAreaTemplate, IdPath},
|
||||
models::{Area, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[actix_web::get("/area/edit/{id}")]
|
||||
async fn get(
|
||||
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 let Some(area_in_db) = Area::read_by_id(pool.get_ref(), path.id).await? {
|
||||
let template = NewOrEditAreaTemplate {
|
||||
user: user.into_inner(),
|
||||
area: Some(area_in_db),
|
||||
};
|
||||
|
||||
return Ok(template.to_response());
|
||||
} else {
|
||||
return Ok(HttpResponse::NotFound().finish());
|
||||
}
|
||||
}
|
@ -1,14 +1,7 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
|
||||
use crate::models::{Role, User};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "area/new.html")]
|
||||
struct NewAreaTemplate {
|
||||
user: User,
|
||||
}
|
||||
use crate::{endpoints::area::NewOrEditAreaTemplate, models::{Role, User}};
|
||||
|
||||
#[actix_web::get("/area/new")]
|
||||
async fn get(user: web::ReqData<User>) -> impl Responder {
|
||||
@ -16,8 +9,9 @@ async fn get(user: web::ReqData<User>) -> impl Responder {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
}
|
||||
|
||||
let template = NewAreaTemplate {
|
||||
let template = NewOrEditAreaTemplate {
|
||||
user: user.into_inner(),
|
||||
area: None
|
||||
};
|
||||
|
||||
template.to_response()
|
||||
|
@ -1,2 +1,14 @@
|
||||
pub mod get_new;
|
||||
pub mod post_new;
|
||||
pub mod get_edit;
|
||||
|
||||
use askama::Template;
|
||||
|
||||
use crate::models::{Area, Role, User};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "area/new_or_edit.html")]
|
||||
struct NewOrEditAreaTemplate {
|
||||
user: User,
|
||||
area: Option<Area>,
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ pub async fn get(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl Resp
|
||||
.unwrap();
|
||||
let area = Area::read_by_id(pool.get_ref(), user.area_id)
|
||||
.await
|
||||
.unwrap();
|
||||
.unwrap().unwrap();
|
||||
|
||||
grouped_locations = vec![(area, Vec::new())];
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ pub fn init(cfg: &mut ServiceConfig) {
|
||||
|
||||
cfg.service(area::get_new::get);
|
||||
cfg.service(area::post_new::post);
|
||||
cfg.service(area::get_edit::get);
|
||||
|
||||
cfg.service(export::get_availability::get);
|
||||
cfg.service(export::get_availability_data::get);
|
||||
|
@ -27,7 +27,7 @@ pub async fn get_overview(user: Identity, pool: web::Data<PgPool>) -> impl Respo
|
||||
area = Some(
|
||||
Area::read_by_id(pool.get_ref(), current_user.area_id)
|
||||
.await
|
||||
.unwrap(),
|
||||
.unwrap().unwrap(),
|
||||
);
|
||||
users = User::read_all_by_area(pool.get_ref(), current_user.area_id)
|
||||
.await
|
||||
|
@ -16,7 +16,7 @@ pub async fn get(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl Resp
|
||||
let area = Area::read_by_id(pool.get_ref(), user.area_id).await.unwrap();
|
||||
|
||||
let mut user = user.into_inner();
|
||||
user.area = Some(area);
|
||||
user.area = area;
|
||||
|
||||
let template = ProfileTemplate { user };
|
||||
|
||||
|
@ -1,26 +1,33 @@
|
||||
use super::Result;
|
||||
use sqlx::{query, query_as, PgPool};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Area {
|
||||
pub id: i32,
|
||||
pub name: String
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl Area {
|
||||
pub async fn create(pool: &PgPool, name: &str) -> anyhow::Result<i32> {
|
||||
let result = query!("INSERT INTO area (name) VALUES ($1) RETURNING id;", name).fetch_one(pool).await?;
|
||||
pub async fn create(pool: &PgPool, name: &str) -> Result<i32> {
|
||||
let result = query!("INSERT INTO area (name) VALUES ($1) RETURNING id;", name)
|
||||
.fetch_one(pool)
|
||||
.await?;
|
||||
|
||||
Ok(result.id)
|
||||
}
|
||||
|
||||
pub async fn read_by_id(pool: &PgPool, id: i32) -> anyhow::Result<Area> {
|
||||
let record = query_as!(Area, "SELECT * FROM area WHERE id = $1", id).fetch_one(pool).await?;
|
||||
pub async fn read_by_id(pool: &PgPool, id: i32) -> Result<Option<Area>> {
|
||||
let record = query_as!(Area, "SELECT * FROM area WHERE id = $1", id)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
Ok(record)
|
||||
}
|
||||
|
||||
pub async fn read_all(pool: &PgPool) -> anyhow::Result<Vec<Area>> {
|
||||
let records = query_as!(Area, "SELECT * FROM area").fetch_all(pool).await?;
|
||||
pub async fn read_all(pool: &PgPool) -> Result<Vec<Area>> {
|
||||
let records = query_as!(Area, "SELECT * FROM area")
|
||||
.fetch_all(pool)
|
||||
.await?;
|
||||
|
||||
Ok(records)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ pub trait Token {
|
||||
|
||||
pub struct NoneToken {}
|
||||
impl Token for NoneToken {
|
||||
async fn delete(&self, pool: &PgPool) -> Result<()> {
|
||||
async fn delete(&self, _pool: &PgPool) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
{% extends "nav.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<form method="post" action="/area/new">
|
||||
<h1 class="title">Neuen Bereich anlegen</h1>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label">
|
||||
<label class="label">Name</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="name" required placeholder="Leipzig Ost" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label"></div>
|
||||
<div class="field-body">
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-success">
|
||||
<span class="icon">
|
||||
<svg class="feather">
|
||||
<use href="/static/feather-sprite.svg#check-circle" />
|
||||
</svg>
|
||||
</span>
|
||||
<span>Speichern</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/locations">
|
||||
<span class="icon">
|
||||
<svg class="feather">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
</span>
|
||||
<span>Zurück</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
{% endblock %}
|
68
templates/area/new_or_edit.html
Normal file
68
templates/area/new_or_edit.html
Normal file
@ -0,0 +1,68 @@
|
||||
{% extends "nav.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
{% if area.is_some() %}
|
||||
<form method="post" action="/area/edit/{{ area.as_ref().unwrap().id }}">
|
||||
<h1 class="title">Bereich '{{ area.as_ref().unwrap().name }}' anlegen</h1>
|
||||
{% else %}
|
||||
<form method="post" action="/area/new">
|
||||
<h1 class="title">Neuen Bereich anlegen</h1>
|
||||
{% endif %}
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label">
|
||||
<label class="label">Name</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="name" required placeholder="Leipzig Ost" {% if area.is_some() -%}
|
||||
value="{{ area.as_ref().unwrap().name }}" {% endif -%} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label"></div>
|
||||
<div class="field-body">
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-success">
|
||||
<span class="icon">
|
||||
<svg class="feather">
|
||||
<use href="/static/feather-sprite.svg#check-circle" />
|
||||
</svg>
|
||||
</span>
|
||||
<span>
|
||||
{% if area.is_some() %}
|
||||
Speichern
|
||||
{% else %}
|
||||
Erstellen
|
||||
{% endif %}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/locations">
|
||||
<span class="icon">
|
||||
<svg class="feather">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
</span>
|
||||
<span>Zurück</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user