Working overview of klassen
This commit is contained in:
parent
a315bb84a4
commit
5c450ba16c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1001,6 +1001,7 @@ dependencies = [
|
|||||||
"rocket_contrib",
|
"rocket_contrib",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -10,6 +10,7 @@ edition = "2018"
|
|||||||
rocket = "0.4.5"
|
rocket = "0.4.5"
|
||||||
diesel = { version = "1.4", features = ["sqlite"] }
|
diesel = { version = "1.4", features = ["sqlite"] }
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
serde_json = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|
||||||
[dependencies.rocket_contrib]
|
[dependencies.rocket_contrib]
|
||||||
|
BIN
database.sqlite
BIN
database.sqlite
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
-- Your SQL
|
-- Your SQL
|
||||||
|
|
||||||
CREATE TABLE Vertretungen
|
CREATE TABLE vertretungen
|
||||||
(
|
(
|
||||||
id Integer PRIMARY KEY NOT NULL,
|
id Integer PRIMARY KEY NOT NULL,
|
||||||
klassen_id Integer NOT NULL,
|
klassen_id Integer NOT NULL,
|
||||||
|
6
migrations/2020-07-25-085330_rename_id_columns/down.sql
Normal file
6
migrations/2020-07-25-085330_rename_id_columns/down.sql
Normal 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;
|
6
migrations/2020-07-25-085330_rename_id_columns/up.sql
Normal file
6
migrations/2020-07-25-085330_rename_id_columns/up.sql
Normal 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;
|
@ -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;
|
@ -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;
|
79
src/main.rs
79
src/main.rs
@ -8,11 +8,20 @@ extern crate rocket_contrib;
|
|||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
use crate::models::Klassen;
|
use crate::diesel::GroupedBy;
|
||||||
|
use crate::models::{Klasse, Stunde, Vertretung};
|
||||||
use crate::schema::klassen;
|
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 diesel::RunQueryDsl;
|
||||||
use rocket::request::{Form, FromParam};
|
use rocket::request::{Form, FromParam};
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
@ -42,21 +51,84 @@ struct DbConn(databases::diesel::SqliteConnection);
|
|||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct ListAllContext {
|
struct ListAllContext {
|
||||||
klassen: Vec<Klassen>,
|
klassen: Vec<(Klasse, Vec<Vertretung>)>,
|
||||||
parent: String,
|
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("/")]
|
#[get("/")]
|
||||||
fn index(conn: DbConn) -> Template {
|
fn index(conn: DbConn) -> Template {
|
||||||
|
let combined_classes = query_all_classes(conn);
|
||||||
Template::render(
|
Template::render(
|
||||||
"uebersicht",
|
"uebersicht",
|
||||||
ListAllContext {
|
ListAllContext {
|
||||||
klassen: klassen::dsl::klassen.load(&*conn).expect("database acess"),
|
klassen: combined_classes,
|
||||||
parent: "base".to_string(),
|
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")]
|
#[get("/add/klasse")]
|
||||||
fn get_klasse_form() -> Template {
|
fn get_klasse_form() -> Template {
|
||||||
Template::render("add_klasse_form", "")
|
Template::render("add_klasse_form", "")
|
||||||
@ -91,6 +163,7 @@ fn main() {
|
|||||||
StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/static")),
|
StaticFiles::from(concat!(env!("CARGO_MANIFEST_DIR"), "/static")),
|
||||||
)
|
)
|
||||||
.mount("/", routes![index])
|
.mount("/", routes![index])
|
||||||
|
.mount("/", routes![klasse_view])
|
||||||
.mount("/admin/", routes![get_klasse_form])
|
.mount("/admin/", routes![get_klasse_form])
|
||||||
.mount("/admin/", routes![post_klasse_form])
|
.mount("/admin/", routes![post_klasse_form])
|
||||||
.launch();
|
.launch();
|
||||||
|
@ -1,39 +1,43 @@
|
|||||||
use super::schema::{klassen, vertretungen};
|
use super::schema::{klassen, vertretungen};
|
||||||
|
use std::cmp::Eq;
|
||||||
|
|
||||||
#[derive(Queryable, Debug, Serialize)]
|
#[derive(Queryable, Debug, Serialize, Hash, PartialEq, Clone)]
|
||||||
pub struct Stunden {
|
pub struct Stunde {
|
||||||
pub id: i32,
|
pub stunden_id: i32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub short: String,
|
pub short: String,
|
||||||
pub ordinal: i32,
|
pub ordinal: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for Stunde {}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Debug, Serialize, Associations)]
|
#[derive(Identifiable, Queryable, Debug, Serialize, Associations)]
|
||||||
#[belongs_to(Klassen)]
|
#[belongs_to(Klasse)]
|
||||||
#[belongs_to(Stunden)]
|
#[belongs_to(Stunde)]
|
||||||
#[table_name = "vertretungen"]
|
#[table_name = "vertretungen"]
|
||||||
pub struct Vertretungen {
|
pub struct Vertretung {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub klassen_id: i32,
|
pub klasse_id: i32,
|
||||||
pub stunden_id: i32,
|
pub stunde_id: i32,
|
||||||
pub fehlend: String,
|
pub fehlend: String,
|
||||||
pub vertretung: String,
|
pub vertretung: String,
|
||||||
pub kommentar: String,
|
pub kommentar: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Debug, Serialize)]
|
#[derive(Identifiable, Queryable, Debug, Serialize, Associations)]
|
||||||
#[table_name = "klassen"]
|
#[table_name = "klassen"]
|
||||||
pub struct Klassen {
|
#[primary_key(klassen_id)]
|
||||||
pub id: i32,
|
pub struct Klasse {
|
||||||
|
pub klassen_id: i32,
|
||||||
pub stufe: i32,
|
pub stufe: i32,
|
||||||
pub gruppe: String,
|
pub gruppe: String,
|
||||||
pub titel: Option<String>,
|
pub titel: Option<String>,
|
||||||
pub ordnung: i32,
|
pub ordnung: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable)]
|
#[derive(Serialize, Insertable)]
|
||||||
#[table_name = "klassen"]
|
#[table_name = "klassen"]
|
||||||
pub struct NewKlassen {
|
pub struct NewKlasse {
|
||||||
pub stufe: i32,
|
pub stufe: i32,
|
||||||
pub gruppe: String,
|
pub gruppe: String,
|
||||||
pub titel: Option<String>,
|
pub titel: Option<String>,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
table! {
|
table! {
|
||||||
vertretungen (id) {
|
vertretungen (vertretungen_id) {
|
||||||
id -> Integer,
|
vertretungen_id -> Integer,
|
||||||
klassen_id -> Integer,
|
klasse_id -> Integer,
|
||||||
stunden_id -> Integer,
|
stunde_id -> Integer,
|
||||||
fehlend -> Text,
|
fehlend -> Text,
|
||||||
vertretung -> Text,
|
vertretung -> Text,
|
||||||
kommentar -> Text,
|
kommentar -> Text,
|
||||||
@ -10,8 +10,8 @@ table! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
klassen (id) {
|
klassen (klassen_id) {
|
||||||
id -> Integer,
|
klassen_id -> Integer,
|
||||||
stufe -> Integer,
|
stufe -> Integer,
|
||||||
gruppe -> Text,
|
gruppe -> Text,
|
||||||
titel -> Nullable<Text>,
|
titel -> Nullable<Text>,
|
||||||
@ -20,8 +20,8 @@ table! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
stunden (id) {
|
stunden (stunden_id) {
|
||||||
id -> Integer,
|
stunden_id -> Integer,
|
||||||
title -> Text,
|
title -> Text,
|
||||||
short -> Text,
|
short -> Text,
|
||||||
ordinal -> Integer,
|
ordinal -> Integer,
|
||||||
|
@ -19,27 +19,53 @@ a:hover {
|
|||||||
a:visited {
|
a:visited {
|
||||||
color: #fcb6b6;
|
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 {
|
.grid-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto auto auto auto;
|
grid-template-columns: auto auto auto auto;
|
||||||
grid-gap: 30px;
|
grid-gap: 30px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #23272a;
|
background-color: #005a9e;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-item div {
|
.grid-item {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
font-size: 48px;
|
|
||||||
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.2);
|
box-shadow: 2px 2px 6px 0px rgba(0, 0, 0, 0.2);
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
width: 215px;
|
width: 215px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 200px;
|
/*line-height: 200px;*/
|
||||||
background-color: #2c2f33;
|
background-color: #0050b8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid {
|
.grid {
|
||||||
|
27
templates/klasse.hbs
Normal file
27
templates/klasse.hbs
Normal 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)~}}
|
@ -1,10 +1,12 @@
|
|||||||
{{#* inline "page"}}
|
{{#* inline "page"}}
|
||||||
<h1>Vertretungen</h1>
|
<h1>Vertretungen</h1>
|
||||||
<ul>
|
<div class="grid-container">
|
||||||
{{#each klassen}}
|
{{#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}}
|
{{/each}}
|
||||||
</ul>
|
</div>
|
||||||
{{/inline}}
|
{{/inline}}
|
||||||
{{! remove whitespaces with ~ }}
|
{{! remove whitespaces with ~ }}
|
||||||
{{~> (parent)~}}
|
{{~> (parent)~}}
|
Loading…
Reference in New Issue
Block a user