Working overview of klassen

This commit is contained in:
Dietrich 2020-07-26 11:36:54 +02:00
parent a315bb84a4
commit 5c450ba16c
14 changed files with 191 additions and 39 deletions

1
Cargo.lock generated
View File

@ -1001,6 +1001,7 @@ dependencies = [
"rocket_contrib",
"serde",
"serde_derive",
"serde_json",
]
[[package]]

View File

@ -10,6 +10,7 @@ edition = "2018"
rocket = "0.4.5"
diesel = { version = "1.4", features = ["sqlite"] }
serde_derive = "1.0"
serde_json = "1.0"
serde = "1.0"
[dependencies.rocket_contrib]

Binary file not shown.

View File

@ -1,6 +1,6 @@
-- Your SQL
CREATE TABLE Vertretungen
CREATE TABLE vertretungen
(
id Integer PRIMARY KEY NOT NULL,
klassen_id Integer NOT NULL,

View File

@ -0,0 +1,6 @@
-- This file should undo anything in `up.sql`
ALTER TABLE klassen RENAME COLUMN klassen_id TO id;
ALTER TABLE vertretungen RENAME COLUMN vertretungen_id TO id;
ALTER TABLE vertretungen RENAME COLUMN klassen_id TO klasse_id;
ALTER TABLE vertretungen RENAME COLUMN stunden_id TO stunde_id;
ALTER TABLE stunden RENAME COLUMN stunden_id TO id;

View File

@ -0,0 +1,6 @@
-- Your SQL goes here
ALTER TABLE klassen RENAME COLUMN id TO klassen_id;
ALTER TABLE vertretungen RENAME COLUMN id TO vertretungen_id;
ALTER TABLE vertretungen RENAME COLUMN klasse_id TO klassen_id;
ALTER TABLE vertretungen RENAME COLUMN stunde_id TO stunden_id;
ALTER TABLE stunden RENAME COLUMN id TO stunden_id;

View File

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
ALTER TABLE vertretungen RENAME COLUMN klasse_id TO klassen_id;
ALTER TABLE vertretungen RENAME COLUMN stunde_id TO stunden_id;

View File

@ -0,0 +1,3 @@
-- Your SQL goes here
ALTER TABLE vertretungen RENAME COLUMN klassen_id TO klasse_id;
ALTER TABLE vertretungen RENAME COLUMN stunden_id TO stunde_id;

View File

@ -8,11 +8,20 @@ extern crate rocket_contrib;
extern crate diesel;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use std::collections::HashMap;
pub mod models;
pub mod schema;
use crate::models::Klassen;
use crate::diesel::GroupedBy;
use crate::models::{Klasse, Stunde, Vertretung};
use crate::schema::klassen;
use crate::schema::stunden;
use crate::schema::vertretungen;
use diesel::prelude::*;
use diesel::BelongingToDsl;
use diesel::QueryDsl;
use diesel::RunQueryDsl;
use rocket::request::{Form, FromParam};
use rocket::response::Redirect;
@ -42,21 +51,84 @@ struct DbConn(databases::diesel::SqliteConnection);
#[derive(Debug, Serialize)]
struct ListAllContext {
klassen: Vec<Klassen>,
klassen: Vec<(Klasse, Vec<Vertretung>)>,
parent: String,
}
enum QueryClasses {
All,
KlassenId(i32),
}
fn query_all_classes(conn: DbConn) -> Vec<(Klasse, Vec<Vertretung>)> {
let all_classes = klassen::table
.load::<Klasse>(&*conn)
.expect("database acess classes");
let and_substitutions = Vertretung::belonging_to(&all_classes)
.load::<Vertretung>(&*conn)
.expect("database acess Vertretungen")
.grouped_by(&all_classes);
let combined_classes = all_classes
.into_iter()
.zip(and_substitutions)
.filter(|x| x.1.len() > 0)
.collect::<Vec<_>>();
combined_classes
}
fn query_one_class<'a>(
conn: DbConn,
id: i32,
) -> (Klasse, HashMap<String, (Stunde, Vec<Vertretung>)>) {
let mut ret: HashMap<String, (Stunde, Vec<Vertretung>)> = HashMap::new();
let class = klassen::dsl::klassen
.filter(klassen::dsl::klassen_id.eq(id))
.first::<Klasse>(&*conn)
.expect("database acess classes");
//let stund: Vec<Stunde> = stunden::table.load(&*conn).expect("Loading Stunden");
let times: Vec<(Vertretung, Stunde)> = Vertretung::belonging_to(&class)
.inner_join(stunden::table.on(vertretungen::stunde_id.eq(stunden::stunden_id)))
.load(&*conn)
.expect("database access Stunden");
for (vert, stun) in times {
let stun_ord = stun.ordinal.to_string();
let verts = ret.entry(stun_ord).or_insert((stun, Vec::new()));
verts.1.push(vert);
}
(class, ret)
}
#[get("/")]
fn index(conn: DbConn) -> Template {
let combined_classes = query_all_classes(conn);
Template::render(
"uebersicht",
ListAllContext {
klassen: klassen::dsl::klassen.load(&*conn).expect("database acess"),
klassen: combined_classes,
parent: "base".to_string(),
},
)
}
#[derive(Debug, Serialize)]
struct ListOneContext {
klasse: Klasse,
vertretungen: HashMap<String, (Stunde, Vec<Vertretung>)>,
parent: String,
}
#[get("/klasse/<class_id>")]
fn klasse_view(conn: DbConn, class_id: i32) -> Template {
let class = query_one_class(conn, class_id);
let (klasse, vertretungen) = class;
let cont = ListOneContext {
klasse: klasse,
vertretungen: vertretungen,
parent: "base".to_string(),
};
Template::render("klasse", cont)
}
#[get("/add/klasse")]
fn get_klasse_form() -> Template {
Template::render("add_klasse_form", "")
@ -91,6 +163,7 @@ fn main() {
StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/static")),
)
.mount("/", routes![index])
.mount("/", routes![klasse_view])
.mount("/admin/", routes![get_klasse_form])
.mount("/admin/", routes![post_klasse_form])
.launch();

View File

@ -1,39 +1,43 @@
use super::schema::{klassen, vertretungen};
use std::cmp::Eq;
#[derive(Queryable, Debug, Serialize)]
pub struct Stunden {
pub id: i32,
#[derive(Queryable, Debug, Serialize, Hash, PartialEq, Clone)]
pub struct Stunde {
pub stunden_id: i32,
pub title: String,
pub short: String,
pub ordinal: i32,
}
impl Eq for Stunde {}
#[derive(Identifiable, Queryable, Debug, Serialize, Associations)]
#[belongs_to(Klassen)]
#[belongs_to(Stunden)]
#[belongs_to(Klasse)]
#[belongs_to(Stunde)]
#[table_name = "vertretungen"]
pub struct Vertretungen {
pub struct Vertretung {
pub id: i32,
pub klassen_id: i32,
pub stunden_id: i32,
pub klasse_id: i32,
pub stunde_id: i32,
pub fehlend: String,
pub vertretung: String,
pub kommentar: String,
}
#[derive(Identifiable, Queryable, Debug, Serialize)]
#[derive(Identifiable, Queryable, Debug, Serialize, Associations)]
#[table_name = "klassen"]
pub struct Klassen {
pub id: i32,
#[primary_key(klassen_id)]
pub struct Klasse {
pub klassen_id: i32,
pub stufe: i32,
pub gruppe: String,
pub titel: Option<String>,
pub ordnung: i32,
}
#[derive(Insertable)]
#[derive(Serialize, Insertable)]
#[table_name = "klassen"]
pub struct NewKlassen {
pub struct NewKlasse {
pub stufe: i32,
pub gruppe: String,
pub titel: Option<String>,

View File

@ -1,8 +1,8 @@
table! {
vertretungen (id) {
id -> Integer,
klassen_id -> Integer,
stunden_id -> Integer,
vertretungen (vertretungen_id) {
vertretungen_id -> Integer,
klasse_id -> Integer,
stunde_id -> Integer,
fehlend -> Text,
vertretung -> Text,
kommentar -> Text,
@ -10,8 +10,8 @@ table! {
}
table! {
klassen (id) {
id -> Integer,
klassen (klassen_id) {
klassen_id -> Integer,
stufe -> Integer,
gruppe -> Text,
titel -> Nullable<Text>,
@ -20,8 +20,8 @@ table! {
}
table! {
stunden (id) {
id -> Integer,
stunden (stunden_id) {
stunden_id -> Integer,
title -> Text,
short -> Text,
ordinal -> Integer,

View File

@ -19,27 +19,53 @@ a:hover {
a:visited {
color: #fcb6b6;
}
div.erkl {
margin-top: 10px;
font-size: 0.7em;
color: #74787c;
}
div.vert {
width:100%;
text-align: center;
margin-top: 5px;
}
table.vertretungsplan {
padding: 15px;
border-spacing: 10px;
}
table.vertretungsplan td, table.vertretungsplan th {
padding: 15px;
width: 130px;
height: 100px;
border: 1px solid rgb(255, 255, 255);
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto auto;
grid-gap: 30px;
padding: 10px;
background-color: #23272a;
background-color: #005a9e;
align-items: stretch;
}
.grid-item div {
.grid-item {
display: table-cell;
border: 1px solid #ccc;
font-size: 48px;
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.2);
max-width: 100%;
width: 215px;
height: 200px;
margin: auto;
text-align: center;
line-height: 200px;
background-color: #2c2f33;
/*line-height: 200px;*/
background-color: #0050b8;
}
.grid {

27
templates/klasse.hbs Normal file
View File

@ -0,0 +1,27 @@
{{#* inline "page"}}
<h1>Klasse {{klasse.stufe}}{{klasse.gruppe}}</h1>
<table class="vertretungsplan">
{{#each vertretungen}}
<tr>
<th class="stunden">
Stunde: {{this.0.title}}
</th>
{{#each this.1}}
<td class="vertretung">
<div>
<div class="erkl">Vertretung für:</div>
<div class="vert">{{this.fehlend}}</div>
</div>
<div>
<div class="erkl">Vertretung durch:</div>
<div class="vert">{{this.vertretung}}</div>
</div>
</td>
{{/each}}
</tr>
{{/each}}
</table>
{{/inline}}
{{! remove whitespaces with ~ }}
{{~> (parent)~}}

View File

@ -1,10 +1,12 @@
{{#* inline "page"}}
<h1>Vertretungen</h1>
<ul>
<h1>Vertretungen</h1>
<div class="grid-container">
{{#each klassen}}
<li>{{this.id}}. {{this.stufe}}{{this.gruppe}}</li>
<div class="grid-item">
<h2>{{this.0.klassen_id}}. {{this.0.stufe}}{{this.0.gruppe}} <br />{{this.1}}</h2>
</div>
{{/each}}
</ul>
{{/inline}}
{{! remove whitespaces with ~ }}
{{~> (parent)~}}
</div>
{{/inline}}
{{! remove whitespaces with ~ }}
{{~> (parent)~}}