feat: add overview of locations and users

This commit is contained in:
Max Hohlfeld 2024-02-18 22:58:35 +01:00
parent a06f86dcaa
commit 6b35eda326
10 changed files with 256 additions and 18 deletions

View File

@ -6,7 +6,7 @@ use chrono::NaiveDate;
use serde::Deserialize; use serde::Deserialize;
use sqlx::PgPool; use sqlx::PgPool;
use crate::models::User; use crate::models::{User, Role};
#[derive(Template)] #[derive(Template)]
#[template(path = "availabillity_new.html")] #[template(path = "availabillity_new.html")]

View File

@ -5,7 +5,7 @@ use chrono::{NaiveDate, Utc};
use serde::Deserialize; use serde::Deserialize;
use sqlx::PgPool; use sqlx::PgPool;
use crate::models::{Area, Availabillity, Event, Function, User}; use crate::models::{Area, Availabillity, Event, Function, User, Role};
use super::{ use super::{
delete_availabillity::delete_availabillity, delete_availabillity::delete_availabillity,

View File

@ -5,7 +5,7 @@ use askama_actix::TemplateToResponse;
use chrono::{NaiveDate, NaiveTime}; use chrono::{NaiveDate, NaiveTime};
use sqlx::PgPool; use sqlx::PgPool;
use crate::{calendar::post_availabillity::AvailabillityForm, models::{Availabillity, User}}; use crate::{calendar::post_availabillity::AvailabillityForm, models::{Availabillity, User, Role}};
use super::delete_availabillity::AvailabillityPath; use super::delete_availabillity::AvailabillityPath;

View File

@ -0,0 +1,32 @@
use actix_identity::Identity;
use actix_web::{web, HttpResponse, Responder};
use askama::Template;
use askama_actix::TemplateToResponse;
use sqlx::PgPool;
use crate::models::{Area, Location, Role, User};
#[derive(Template)]
#[template(path = "locations.html")]
pub struct LocationsTemplate {
user: User,
area: Area,
locations: Vec<Location>
}
#[actix_web::get("/locations")]
pub async fn get(user: Identity, pool: web::Data<PgPool>) -> impl Responder {
let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()).await.unwrap();
if current_user.role == Role::AreaManager {
if let Ok(locations) = Location::read_by_area(pool.get_ref(), current_user.area_id).await {
let area = Area::read_by_id(pool.get_ref(), current_user.area_id).await.unwrap();
let template = LocationsTemplate { user: current_user, area, locations};
return template.to_response()
}
}
return HttpResponse::BadRequest().body("Fehler beim Zugriff auf die Veranstaltungsorte!");
}

10
src/endpoints/mod.rs Normal file
View File

@ -0,0 +1,10 @@
use actix_web::web::ServiceConfig;
mod location;
mod user;
pub fn init(cfg: &mut ServiceConfig) {
cfg.service(location::get);
cfg.service(user::get);
}

38
src/endpoints/user/mod.rs Normal file
View File

@ -0,0 +1,38 @@
use actix_identity::Identity;
use actix_web::{web, HttpResponse, Responder};
use askama::Template;
use askama_actix::TemplateToResponse;
use sqlx::PgPool;
use crate::models::{Area, Role, User};
#[derive(Template)]
#[template(path = "user/overview.html")]
pub struct UsersTemplate {
user: User,
area: Option<Area>,
users: Vec<User>
}
#[actix_web::get("/users")]
pub async fn get(user: Identity, pool: web::Data<PgPool>) -> impl Responder {
let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()).await.unwrap();
if current_user.role == Role::AreaManager || current_user.role == Role::Admin {
let mut area = None;
let users;
if current_user.role == Role::AreaManager {
area = Some(Area::read_by_id(pool.get_ref(), current_user.area_id).await.unwrap());
users = User::read_all_by_area(pool.get_ref(), current_user.area_id).await.unwrap();
} else {
users = User::read_all(pool.get_ref()).await.unwrap();
}
let template = UsersTemplate { user: current_user, area, users};
return template.to_response()
}
return HttpResponse::BadRequest().body("Fehler beim Zugriff auf die Nutzerverwaltung!");
}

View File

@ -75,17 +75,17 @@ impl User {
.await?; .await?;
let user = User { let user = User {
id: record.id, id: record.id,
name: record.name, name: record.name,
email: record.email, email: record.email,
password: record.password, password: record.password,
salt: record.salt, salt: record.salt,
role: record.role, role: record.role,
function: record.function, function: record.function,
area_id: record.areaid, area_id: record.areaid,
locked: record.locked, locked: record.locked,
last_login: record.lastlogin, last_login: record.lastlogin,
receive_notifications: record.receivenotifications, receive_notifications: record.receivenotifications,
}; };
Ok(user) Ok(user)
@ -127,14 +127,92 @@ impl User {
last_login: record.lastlogin, last_login: record.lastlogin,
receive_notifications: record.receivenotifications, receive_notifications: record.receivenotifications,
}), }),
None => None None => None,
}; };
Ok(result) Ok(result)
} }
pub async fn read_all(pool: &PgPool) -> Option<Vec<User>> { pub async fn read_all(pool: &PgPool) -> anyhow::Result<Vec<User>> {
todo!() let records = sqlx::query!(
r#"
SELECT id,
name,
email,
password,
salt,
role AS "role: Role",
function AS "function: Function",
areaId,
locked,
lastLogin,
receiveNotifications
FROM user_;
"#,
)
.fetch_all(pool)
.await?;
let result = records
.iter()
.map(|record| User {
id: record.id,
name: record.name.clone(),
email: record.email.clone(),
password: record.password.clone(),
salt: record.salt.clone(),
role: record.role.clone(),
function: record.function.clone(),
area_id: record.areaid,
locked: record.locked,
last_login: record.lastlogin,
receive_notifications: record.receivenotifications,
})
.collect();
Ok(result)
}
pub async fn read_all_by_area(pool: &PgPool, area_id: i32) -> anyhow::Result<Vec<User>> {
let records = sqlx::query!(
r#"
SELECT id,
name,
email,
password,
salt,
role AS "role: Role",
function AS "function: Function",
areaId,
locked,
lastLogin,
receiveNotifications
FROM user_
WHERE areaId = $1;
"#,
area_id
)
.fetch_all(pool)
.await?;
let result = records
.iter()
.map(|record| User {
id: record.id,
name: record.name.clone(),
email: record.email.clone(),
password: record.password.clone(),
salt: record.salt.clone(),
role: record.role.clone(),
function: record.function.clone(),
area_id: record.areaid,
locked: record.locked,
last_login: record.lastlogin,
receive_notifications: record.receivenotifications,
})
.collect();
Ok(result)
} }
pub async fn update(pool: &PgPool, id: i32, updated_user: User) -> Option<User> { pub async fn update(pool: &PgPool, id: i32, updated_user: User) -> Option<User> {

34
templates/locations.html Normal file
View File

@ -0,0 +1,34 @@
{% extends "nav.html" %}
{% block content %}
<section class="section">
<div class="container">
<div class="level">
<div class="level-left">
<h3 class="title is-3">
Veranstaltungsorte im Bereich {{ area.name }}
</h3>
</div>
<div class="level-right">
<a class="button" href="/event/new">Neues Event für diesen Tag</a>
</div>
</div>
{% if locations.len() == 0 %}
<div class="box">
<h5 class="title is-5">keine Orte vorhanden</h5>
</div>
{% else %}
{% for location in locations %}
<div class="box">
<h5 class="title is-5">{{ location.name }}</h5>
</div>
{% endfor %}
{% endif %}
</div>
</section>
</section>
<script>
</script>
{% endblock %}

View File

@ -21,10 +21,22 @@
</a> </a>
{% match user.role %} {% match user.role %}
{% when AreaManager %} {% when Role::Staff %}
{% when Role::AreaManager %}
<a class="navbar-item"> <a class="navbar-item">
Planung Planung
</a> </a>
<a href="/locations" class="navbar-item">
Veranstaltungsorte
</a>
<a href="/users" class="navbar-item">
Nutzerverwaltung
</a>
{% when Role::Admin %}
<a href="/users" class="navbar-item">
Nutzerverwaltung
</a>
{% endmatch %} {% endmatch %}
</div> </div>

View File

@ -0,0 +1,34 @@
{% extends "nav.html" %}
{% block content %}
<section class="section">
<div class="container">
<div class="level">
<div class="level-left">
<h3 class="title is-3">
Nutzer
</h3>
</div>
<div class="level-right">
<a class="button" href="/users/new">Neuen Nutzer anlegen</a>
</div>
</div>
{% if users.len() == 0 %}
<div class="box">
<h5 class="title is-5">keine Orte vorhanden</h5>
</div>
{% else %}
{% for u in users %}
<div class="box">
<h5 class="title is-5">{{ u.email }}</h5>
</div>
{% endfor %}
{% endif %}
</div>
</section>
</section>
<script>
</script>
{% endblock %}