Feature: Added Qualifications
This commit is contained in:
parent
6fb8358ec8
commit
eeb3cc6a81
|
@ -4,7 +4,7 @@ create table qualification_categories
|
|||
id uuid default uuid_generate_v1() not null
|
||||
constraint qualification_categories_pk
|
||||
primary key,
|
||||
name text,
|
||||
name text not null,
|
||||
description text
|
||||
);
|
||||
|
||||
|
|
|
@ -133,8 +133,9 @@
|
|||
<div class="card bg-light mb-3">
|
||||
<div class="card-header">Qualifikationen</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Light card title</h5>
|
||||
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
|
||||
{{#each qualification_categories}}
|
||||
<b>{{name}}: </b>{{#each qualifications}}<span class="badge badge-secondary">{{name}}</span> {{/each}}<br>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,4 +3,5 @@ pub mod connector;
|
|||
pub mod groups;
|
||||
pub mod member_licenses;
|
||||
pub mod members;
|
||||
pub mod qualifications;
|
||||
pub mod users;
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
use crate::database::controller::connector::establish_connection;
|
||||
use crate::database::model::qualifications::RawQualificationCategory;
|
||||
use crate::helper::settings::Settings;
|
||||
use crate::modules::member_management::model::qualifications::{
|
||||
Qualification, QualificationCategory,
|
||||
};
|
||||
use diesel::{ExpressionMethods, JoinOnDsl, QueryDsl, RunQueryDsl};
|
||||
use rocket::State;
|
||||
|
||||
pub fn get_raw_qualification_categories(
|
||||
settings: &State<Settings>,
|
||||
) -> Vec<RawQualificationCategory> {
|
||||
use crate::schema::qualification_categories::dsl::*;
|
||||
|
||||
let connection = establish_connection(settings);
|
||||
|
||||
let data: Result<Vec<RawQualificationCategory>, diesel::result::Error> =
|
||||
qualification_categories.load(&connection);
|
||||
|
||||
match data {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
error!("Couldn't read Qualification categories: {}", e);
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_qualifcation_categories(
|
||||
settings: &State<Settings>,
|
||||
member_entity_id: uuid::Uuid,
|
||||
) -> Vec<QualificationCategory> {
|
||||
let raw_categories = get_raw_qualification_categories(settings);
|
||||
let mut categories: Vec<QualificationCategory> = vec![];
|
||||
|
||||
for category in raw_categories {
|
||||
let qualifications =
|
||||
get_qualifications_for_member_for_category(settings, member_entity_id, category.id);
|
||||
categories.push(QualificationCategory {
|
||||
id: category.id,
|
||||
name: category.name,
|
||||
description: category.description,
|
||||
qualifications,
|
||||
})
|
||||
}
|
||||
|
||||
categories
|
||||
}
|
||||
|
||||
pub fn get_qualifications_for_member_for_category(
|
||||
settings: &State<Settings>,
|
||||
member_entity_id: uuid::Uuid,
|
||||
category_id: uuid::Uuid,
|
||||
) -> Vec<Qualification> {
|
||||
use crate::schema::qualifications::dsl::*;
|
||||
use crate::schema::qualifications_members::dsl::*;
|
||||
|
||||
let connection = establish_connection(settings);
|
||||
|
||||
let data: Result<Vec<Qualification>, diesel::result::Error> = qualifications
|
||||
.left_join(qualifications_members.on(qualification_id.eq(id)))
|
||||
.filter(member_id.eq(member_entity_id))
|
||||
.filter(category.eq(category_id))
|
||||
.select((id, name, description))
|
||||
.load(&connection);
|
||||
|
||||
match data {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Couldn't read Qualifications for category {} for member {}: {}",
|
||||
category_id, member_entity_id, e
|
||||
);
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,4 +3,5 @@ pub mod entities;
|
|||
pub mod groups;
|
||||
pub mod member_licenses;
|
||||
pub mod members;
|
||||
pub mod qualifications;
|
||||
pub mod users;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#[derive(Serialize, Queryable, Clone)]
|
||||
pub struct RawQualificationCategory {
|
||||
pub(crate) id: uuid::Uuid,
|
||||
pub(crate) name: String,
|
||||
pub(crate) description: Option<String>,
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
use crate::database::controller::addresses::get_addresses_for_entity_only_one_allowed;
|
||||
use crate::database::controller::member_licenses::get_member_licenses;
|
||||
use crate::database::controller::members::get_raw_member_by_uuid;
|
||||
use crate::database::controller::qualifications::get_qualifcation_categories;
|
||||
use crate::helper::age_calculator::calculate_age;
|
||||
use crate::helper::settings::Settings;
|
||||
use crate::helper::sitebuilder::model::general::{Footer, Header, Stylesheet};
|
||||
use crate::helper::sitebuilder::model::sidebar::Sidebar;
|
||||
use crate::modules::member_management::model::member::Member;
|
||||
use crate::modules::member_management::model::member_module::MemberModuleProfile;
|
||||
use rocket::http::Status;
|
||||
use rocket::State;
|
||||
use rocket_contrib::templates::Template;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn handle_view(
|
||||
settings: &State<Settings>,
|
||||
id: String,
|
||||
member: Member,
|
||||
) -> Result<Template, Status> {
|
||||
let uuid = match uuid::Uuid::from_str(&id) {
|
||||
Ok(uuid) => uuid,
|
||||
Err(e) => {
|
||||
warn!("Tried to view member with invalid uuid: {}", e);
|
||||
return Err(Status::NotFound);
|
||||
}
|
||||
};
|
||||
let raw_member = match get_raw_member_by_uuid(uuid, settings) {
|
||||
Some(member) => member,
|
||||
None => return Err(Status::NotFound),
|
||||
};
|
||||
|
||||
let header = Header {
|
||||
html_language: "de".to_string(),
|
||||
site_title: "Member Profile".to_string(),
|
||||
stylesheets: vec![Stylesheet {
|
||||
path: "/css/errms.css".to_string(),
|
||||
}],
|
||||
};
|
||||
let footer = Footer { scripts: vec![] };
|
||||
let mut sidebar = Sidebar::new(member.clone());
|
||||
sidebar.member_management.active = true;
|
||||
|
||||
let age = match raw_member.date_of_birth {
|
||||
Some(date) => Some(calculate_age(date)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let address = get_addresses_for_entity_only_one_allowed(settings, raw_member.entity_id);
|
||||
let licenses = get_member_licenses(settings, raw_member.entity_id);
|
||||
let qualification_categories = get_qualifcation_categories(settings, raw_member.entity_id);
|
||||
|
||||
return Ok(Template::render(
|
||||
"module_member_management_profile",
|
||||
MemberModuleProfile {
|
||||
header,
|
||||
footer,
|
||||
member: raw_member,
|
||||
member_age: age,
|
||||
address,
|
||||
licenses,
|
||||
qualification_categories,
|
||||
readonly: true,
|
||||
sidebar,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn handle_edit() -> Result<Template, Status> {
|
||||
return Err(Status::NotImplemented);
|
||||
}
|
||||
|
||||
pub fn handle_delete() -> Result<Template, Status> {
|
||||
return Err(Status::NotImplemented);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
pub mod filter_form_from_form_trait;
|
||||
pub mod licenses_trait;
|
||||
pub mod member_check_permission;
|
||||
pub mod member_profile;
|
||||
pub mod member_trait;
|
||||
pub mod render;
|
||||
|
|
|
@ -5,6 +5,9 @@ use crate::helper::sitebuilder::model::sidebar::Sidebar;
|
|||
use crate::modules::member_management::model::group::Group;
|
||||
use crate::modules::member_management::model::licenses::MemberLicense;
|
||||
use crate::modules::member_management::model::member::MemberWithAccess;
|
||||
use crate::modules::member_management::model::qualifications::{
|
||||
Qualification, QualificationCategory,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Serialize)]
|
||||
|
@ -24,6 +27,7 @@ pub struct MemberModuleProfile {
|
|||
pub member_age: Option<i32>,
|
||||
pub address: Option<Address>,
|
||||
pub licenses: Vec<MemberLicense>,
|
||||
pub qualification_categories: Vec<QualificationCategory>,
|
||||
pub readonly: bool,
|
||||
pub sidebar: Sidebar,
|
||||
}
|
||||
|
|
|
@ -3,3 +3,4 @@ pub mod group;
|
|||
pub mod licenses;
|
||||
pub mod member;
|
||||
pub mod member_module;
|
||||
pub mod qualifications;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#[derive(Serialize, Deserialize, Queryable, Clone)]
|
||||
pub struct QualificationCategory {
|
||||
pub(crate) id: uuid::Uuid,
|
||||
pub(crate) name: String,
|
||||
pub(crate) description: Option<String>,
|
||||
pub(crate) qualifications: Vec<Qualification>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Queryable, Clone)]
|
||||
pub struct Qualification {
|
||||
pub(crate) id: uuid::Uuid,
|
||||
pub(crate) name: String,
|
||||
pub(crate) description: Option<String>,
|
||||
}
|
|
@ -6,6 +6,9 @@ use crate::helper::session_cookies::model::SessionCookie;
|
|||
use crate::helper::settings::Settings;
|
||||
use crate::helper::sitebuilder::model::general::{Footer, Header, Stylesheet};
|
||||
use crate::helper::sitebuilder::model::sidebar::Sidebar;
|
||||
use crate::modules::member_management::controller::member_profile::{
|
||||
handle_delete, handle_edit, handle_view,
|
||||
};
|
||||
use crate::modules::member_management::model::member::Member;
|
||||
use crate::modules::member_management::model::member_module::MemberModuleProfile;
|
||||
use rocket::http::Status;
|
||||
|
@ -35,62 +38,3 @@ pub fn member_management_core_data_get(
|
|||
_ => return Err(Status::NotFound),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_view(
|
||||
settings: &State<Settings>,
|
||||
id: String,
|
||||
member: Member,
|
||||
) -> Result<Template, Status> {
|
||||
let uuid = match uuid::Uuid::from_str(&id) {
|
||||
Ok(uuid) => uuid,
|
||||
Err(e) => {
|
||||
warn!("Tried to view member with invalid uuid: {}", e);
|
||||
return Err(Status::NotFound);
|
||||
}
|
||||
};
|
||||
let raw_member = match get_raw_member_by_uuid(uuid, settings) {
|
||||
Some(member) => member,
|
||||
None => return Err(Status::NotFound),
|
||||
};
|
||||
|
||||
let header = Header {
|
||||
html_language: "de".to_string(),
|
||||
site_title: "Member Profile".to_string(),
|
||||
stylesheets: vec![Stylesheet {
|
||||
path: "/css/errms.css".to_string(),
|
||||
}],
|
||||
};
|
||||
let footer = Footer { scripts: vec![] };
|
||||
let mut sidebar = Sidebar::new(member.clone());
|
||||
sidebar.member_management.active = true;
|
||||
|
||||
let age = match raw_member.date_of_birth {
|
||||
Some(date) => Some(calculate_age(date)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let address = get_addresses_for_entity_only_one_allowed(settings, raw_member.entity_id);
|
||||
let licenses = get_member_licenses(settings, raw_member.entity_id);
|
||||
|
||||
return Ok(Template::render(
|
||||
"module_member_management_profile",
|
||||
MemberModuleProfile {
|
||||
header,
|
||||
footer,
|
||||
member: raw_member,
|
||||
member_age: age,
|
||||
address,
|
||||
licenses,
|
||||
readonly: true,
|
||||
sidebar,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn handle_edit() -> Result<Template, Status> {
|
||||
return Err(Status::NotImplemented);
|
||||
}
|
||||
|
||||
pub fn handle_delete() -> Result<Template, Status> {
|
||||
return Err(Status::NotImplemented);
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ table! {
|
|||
|
||||
qualification_categories (id) {
|
||||
id -> Uuid,
|
||||
name -> Nullable<Text>,
|
||||
name -> Text,
|
||||
description -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue