mirror of
https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator.git
synced 2026-04-12 16:55:04 +02:00
Switch from maud to el
This commit is contained in:
parent
28fcb43832
commit
b174b796ed
5 changed files with 347 additions and 219 deletions
59
Cargo.lock
generated
59
Cargo.lock
generated
|
|
@ -110,9 +110,9 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"clap",
|
"clap",
|
||||||
|
"el",
|
||||||
"fontdb 0.23.0",
|
"fontdb 0.23.0",
|
||||||
"jiff",
|
"jiff",
|
||||||
"maud",
|
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
"typst",
|
"typst",
|
||||||
|
|
@ -610,6 +610,16 @@ version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "el"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16d62f2117df9caa2f568124894462af4ba7dfd9a2ab8b82b79c29ce3b0c16eb"
|
||||||
|
dependencies = [
|
||||||
|
"axum-core",
|
||||||
|
"http",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embedded-io"
|
name = "embedded-io"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -1307,30 +1317,6 @@ version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "maud"
|
|
||||||
version = "0.26.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df518b75016b4289cdddffa1b01f2122f4a49802c93191f3133f6dc2472ebcaa"
|
|
||||||
dependencies = [
|
|
||||||
"axum-core",
|
|
||||||
"http",
|
|
||||||
"itoa",
|
|
||||||
"maud_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "maud_macros"
|
|
||||||
version = "0.26.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa453238ec218da0af6b11fc5978d3b5c3a45ed97b722391a2a11f3306274e18"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-error",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
|
@ -1658,29 +1644,6 @@ dependencies = [
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-error-attr",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-error-attr"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.92"
|
version = "1.0.92"
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ anyhow = "1.0.94"
|
||||||
axum = "0.7.9"
|
axum = "0.7.9"
|
||||||
axum-extra = { version = "0.9.6", features = ["form"] }
|
axum-extra = { version = "0.9.6", features = ["form"] }
|
||||||
clap = { version = "4.5.23", features = ["derive", "deprecated"] }
|
clap = { version = "4.5.23", features = ["derive", "deprecated"] }
|
||||||
|
el = { version = "0.1.2", features = ["axum"] }
|
||||||
fontdb = "0.23.0"
|
fontdb = "0.23.0"
|
||||||
jiff = "0.1.15"
|
jiff = "0.1.15"
|
||||||
maud = { version = "0.26.0", features = ["axum"] }
|
|
||||||
serde = { version = "1.0.216", features = ["derive"] }
|
serde = { version = "1.0.216", features = ["derive"] }
|
||||||
tokio = { version = "1.42.0", features = ["full"] }
|
tokio = { version = "1.42.0", features = ["full"] }
|
||||||
typst = "0.12.0"
|
typst = "0.12.0"
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
use maud::{html, Markup};
|
use el::{html::*, Document, ElementComponent};
|
||||||
|
|
||||||
pub mod index;
|
pub mod index;
|
||||||
pub mod tsg;
|
pub mod tsg;
|
||||||
|
|
||||||
fn page(head: Markup, body: Markup) -> Markup {
|
fn page(head: impl ElementComponent, body: impl ElementComponent) -> Document {
|
||||||
html! {
|
html((
|
||||||
(maud::DOCTYPE)
|
el::html::head((
|
||||||
html lang="en" {
|
meta((
|
||||||
head {
|
attr::name("viewport"),
|
||||||
meta charset="utf-8";
|
attr::content("width=device-width, initial-scale=1"),
|
||||||
meta name="viewport" content="width=device-width, initial-scale=1";
|
)),
|
||||||
title { "AbzDokGen" }
|
title("AbzDokGen"),
|
||||||
(head)
|
head,
|
||||||
}
|
)),
|
||||||
body { (body) }
|
el::html::body(body),
|
||||||
}
|
))
|
||||||
}
|
.into_document()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
http::{header, StatusCode},
|
http::{header, StatusCode},
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
};
|
};
|
||||||
use axum_extra::extract::Form;
|
use axum_extra::extract::Form;
|
||||||
|
use el::{html::*, Document};
|
||||||
use jiff::{ToSpan, Zoned};
|
use jiff::{ToSpan, Zoned};
|
||||||
use maud::{html, Markup, PreEscaped};
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -12,7 +14,12 @@ use crate::{
|
||||||
render::{self, Entry, Note, Timesheet, WorkingArea},
|
render::{self, Entry, Note, Timesheet, WorkingArea},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn get() -> Markup {
|
const LINK_SOURCE: &str = "https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator";
|
||||||
|
const LINK_TSG: &str = "https://github.com/kit-sdq/TimeSheetGenerator";
|
||||||
|
const LINK_TEMPLATE: &str =
|
||||||
|
"https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator/blob/master/kit_timesheet.md";
|
||||||
|
|
||||||
|
pub async fn get() -> Document {
|
||||||
// We assume that people still want to fill out the previous month's time
|
// We assume that people still want to fill out the previous month's time
|
||||||
// sheet during the first two weeks of the following month.
|
// sheet during the first two weeks of the following month.
|
||||||
let month = Zoned::now()
|
let month = Zoned::now()
|
||||||
|
|
@ -20,117 +27,252 @@ pub async fn get() -> Markup {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.strftime("%Y-%m");
|
.strftime("%Y-%m");
|
||||||
|
|
||||||
page(
|
let head = (
|
||||||
html! {
|
style(include_str!("index.css")),
|
||||||
style { (PreEscaped(include_str!("index.css"))) }
|
script((attr::TypeScript::Module, include_str!("index.js"))),
|
||||||
script type="module" { (PreEscaped(include_str!("index.js"))) }
|
);
|
||||||
},
|
|
||||||
html! {
|
|
||||||
form #form {
|
|
||||||
h1 {
|
|
||||||
"Arbeitszeitdokumentationsgenerator "
|
|
||||||
a #source href="https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator" { "(source)" }
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
let body = form((
|
||||||
"Du kannst auch "
|
attr::id("form"),
|
||||||
a href="tsg/" { "JSON eingeben" }
|
h1((
|
||||||
", das kompatibel mit dem "
|
"Arbeitszeitdokumentationsgenerator ",
|
||||||
a href="https://github.com/kit-sdq/TimeSheetGenerator" { "TimeSheetGenerator" }
|
a((attr::id("source"), attr::href(LINK_SOURCE), "(source)")),
|
||||||
" ist, oder das dem Generator zugrunde liegende "
|
)),
|
||||||
a href="https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator/blob/master/kit_timesheet.md" { "Typst-Template" }
|
p((
|
||||||
" direkt benutzen."
|
"Du kannst auch ",
|
||||||
}
|
a((attr::href("tsg/"), "JSON eingeben")),
|
||||||
|
", das kompatibel mit dem ",
|
||||||
|
a((attr::href(LINK_TSG), "TimeSheetGenerator")),
|
||||||
|
" ist, oder das dem Generator zugrunde liegende ",
|
||||||
|
a((attr::href(LINK_TEMPLATE), "Typst-Template")),
|
||||||
|
" direkt benutzen.",
|
||||||
|
)),
|
||||||
|
div((
|
||||||
|
attr::id("header"),
|
||||||
|
label((attr::id("l-month"), attr::r#for("i-month"), "Monat / Jahr:")),
|
||||||
|
input((
|
||||||
|
attr::id("i-month"),
|
||||||
|
attr::name("month"),
|
||||||
|
attr::TypeInput::Month,
|
||||||
|
attr::placeholder(&month),
|
||||||
|
attr::value(&month),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("l-name"),
|
||||||
|
attr::r#for("i-name"),
|
||||||
|
"Name, Vorname des/r Beschäftigten:",
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::id("i-name"),
|
||||||
|
attr::class("twocol"),
|
||||||
|
attr::name("name"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("McStudentface, Student"),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("l-staffid"),
|
||||||
|
attr::r#for("i-staffid"),
|
||||||
|
"Personalnummer:",
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::id("i-staffid"),
|
||||||
|
attr::name("staff_id"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("1337420"),
|
||||||
|
)),
|
||||||
|
div((
|
||||||
|
attr::id("gfub"),
|
||||||
|
label((
|
||||||
|
attr::id("l-gf"),
|
||||||
|
attr::title("Großforschung"),
|
||||||
|
"GF: ",
|
||||||
|
input((
|
||||||
|
attr::id("i-gf"),
|
||||||
|
attr::name("working_area"),
|
||||||
|
attr::TypeInput::Radio,
|
||||||
|
attr::value("GF"),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("l-ub"),
|
||||||
|
attr::title("Unibereich"),
|
||||||
|
"UB: ",
|
||||||
|
input((
|
||||||
|
attr::id("i-ub"),
|
||||||
|
attr::name("working_area"),
|
||||||
|
attr::TypeInput::Radio,
|
||||||
|
attr::value("UB"),
|
||||||
|
attr::checked(),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("l-department"),
|
||||||
|
attr::r#for("i-department"),
|
||||||
|
attr::title("Institut/Organisationseinheit"),
|
||||||
|
"OE:",
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::id("i-department"),
|
||||||
|
attr::class("twocol"),
|
||||||
|
attr::name("department"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("Institut für Informatik"),
|
||||||
|
attr::value("Institut für Informatik"),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("l-monthlyhours"),
|
||||||
|
attr::r#for("i-monthlyhours"),
|
||||||
|
"Vertraglich vereinbarte Arbeitszeit:",
|
||||||
|
)),
|
||||||
|
div((
|
||||||
|
attr::id("mhhr"),
|
||||||
|
attr::class("twocol"),
|
||||||
|
span((
|
||||||
|
input((
|
||||||
|
attr::id("i-monthlyhours"),
|
||||||
|
attr::name("monthly_hours"),
|
||||||
|
attr::TypeInput::Number,
|
||||||
|
attr::value(40),
|
||||||
|
attr::min(0),
|
||||||
|
)),
|
||||||
|
" Std.",
|
||||||
|
)),
|
||||||
|
span((
|
||||||
|
label((
|
||||||
|
attr::id("l-hourlywage"),
|
||||||
|
attr::r#for("i-hourlywage"),
|
||||||
|
"Stundensatz: ",
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::id("i-hourlywage"),
|
||||||
|
attr::name("hourly_wage"),
|
||||||
|
attr::TypeInput::Number,
|
||||||
|
attr::step(0.01),
|
||||||
|
attr::value(14.09),
|
||||||
|
)),
|
||||||
|
" €",
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
div((
|
||||||
|
attr::id("carry"),
|
||||||
|
attr::class("twocol"),
|
||||||
|
span((
|
||||||
|
label((
|
||||||
|
attr::id("l-carry"),
|
||||||
|
attr::r#for("i-carry"),
|
||||||
|
"Übertrag vom Vormonat: ",
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::id("i-carry"),
|
||||||
|
attr::class("i-dur"),
|
||||||
|
attr::name("carry_prev_month"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("00:00"),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("check"),
|
||||||
|
attr::title(concat!(
|
||||||
|
"Die Tabelleneinträge werden chronologisch sortiert,",
|
||||||
|
" anstatt dass ihre Reihenfolge beibehalten wird."
|
||||||
|
)),
|
||||||
|
"Einträge sortieren ",
|
||||||
|
input((
|
||||||
|
attr::name("sort"),
|
||||||
|
attr::TypeInput::Checkbox,
|
||||||
|
attr::value(true),
|
||||||
|
attr::checked(),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::id("validate"),
|
||||||
|
attr::title(concat!(
|
||||||
|
"Die Tabelleneinträge werden auf Konsistenz und Korrektheit überprüft,",
|
||||||
|
" bevor das Dokument generiert wird."
|
||||||
|
)),
|
||||||
|
"Einträge validieren ",
|
||||||
|
input((
|
||||||
|
attr::name("validate"),
|
||||||
|
attr::TypeInput::Checkbox,
|
||||||
|
attr::value(true),
|
||||||
|
attr::checked(),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
div((
|
||||||
|
attr::id("table"),
|
||||||
|
div((
|
||||||
|
attr::id("task"),
|
||||||
|
"Tätigkeit",
|
||||||
|
br(()),
|
||||||
|
"(Stichwort, Projekt)",
|
||||||
|
)),
|
||||||
|
div("Tag"),
|
||||||
|
div("Beginn"),
|
||||||
|
div("Ende"),
|
||||||
|
div("Pause"),
|
||||||
|
div("Arbeitszeit"),
|
||||||
|
div(()),
|
||||||
|
div("(hh:mm)"),
|
||||||
|
div("(hh:mm)"),
|
||||||
|
div("(hh:mm)"),
|
||||||
|
div(()),
|
||||||
|
iter::repeat((
|
||||||
|
div(input((
|
||||||
|
attr::class("i-task"),
|
||||||
|
attr::name("task"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
))),
|
||||||
|
div(input((
|
||||||
|
attr::class("i-day"),
|
||||||
|
attr::name("day"),
|
||||||
|
attr::TypeInput::Number,
|
||||||
|
attr::placeholder(1),
|
||||||
|
attr::min(1),
|
||||||
|
attr::max(31),
|
||||||
|
))),
|
||||||
|
div(input((
|
||||||
|
attr::class("i-dur"),
|
||||||
|
attr::name("start"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("12:34"),
|
||||||
|
))),
|
||||||
|
div(input((
|
||||||
|
attr::class("i-dur"),
|
||||||
|
attr::name("end"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("12:34"),
|
||||||
|
))),
|
||||||
|
div(input((
|
||||||
|
attr::class("i-dur"),
|
||||||
|
attr::name("rest"),
|
||||||
|
attr::TypeInput::Text,
|
||||||
|
attr::placeholder("00:00"),
|
||||||
|
))),
|
||||||
|
div(select((
|
||||||
|
attr::name("note"),
|
||||||
|
attr::value(""),
|
||||||
|
option((attr::value(""), "Normal")),
|
||||||
|
option((attr::value("U"), "Urlaub")),
|
||||||
|
option((attr::value("K"), "Krankheit")),
|
||||||
|
option((attr::value("F"), "Feiertag")),
|
||||||
|
option((attr::value("S"), "Sonstiges")),
|
||||||
|
))),
|
||||||
|
))
|
||||||
|
.take(22)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)),
|
||||||
|
button((
|
||||||
|
attr::id("submit"),
|
||||||
|
attr::TypeButton::Button,
|
||||||
|
"Arbeitszeitdokumentation generieren",
|
||||||
|
)),
|
||||||
|
pre(attr::id("info")),
|
||||||
|
));
|
||||||
|
|
||||||
div #header {
|
page(head, body)
|
||||||
label #l-month for="i-month" { "Monat / Jahr:" }
|
|
||||||
input #i-month name="month" type="month" placeholder=(month) value=(month) {}
|
|
||||||
|
|
||||||
label #l-name for="i-name" { "Name, Vorname des/r Beschäftigten:" }
|
|
||||||
input #i-name .twocol name="name" type="text" placeholder="McStudentface, Student" {}
|
|
||||||
|
|
||||||
label #l-staffid for="i-staffid" { "Personalnummer:" }
|
|
||||||
input #i-staffid name="staff_id" type="text" placeholder="1337420" {}
|
|
||||||
|
|
||||||
div #gfub {
|
|
||||||
label #l-gf title="Großforschung" { "GF: "
|
|
||||||
input #i-gf name="working_area" type="radio" value="GF" {}
|
|
||||||
}
|
|
||||||
|
|
||||||
label #l-ub for="i-ub" title="Unibereich" { "UB: "
|
|
||||||
input #i-ub name="working_area" type="radio" value="UB" checked {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label #l-department for="i-department" title="Organisationseinheit" { "OE:" }
|
|
||||||
input #i-department .twocol name="department" type="text" placeholder="Institut für Informatik" value="Institut für Informatik" {}
|
|
||||||
|
|
||||||
label #l-monthlyhours for="i-monthlyhours" { "Vertraglich vereinbarte Arbeitszeit:" }
|
|
||||||
div #mhhr .twocol {
|
|
||||||
span {
|
|
||||||
input #i-monthlyhours name="monthly_hours" type="number" value="40" min="0" {}
|
|
||||||
" Std."
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
label #l-hourlywage for="i-hourlywage" { "Stundensatz: " }
|
|
||||||
input #i-hourlywage name="hourly_wage" type="number" step="0.01" value="14.09" {}
|
|
||||||
" €"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
div #carry .twocol {
|
|
||||||
span {
|
|
||||||
label #l-carry for="i-carry" { "Übertrag vom Vormonat: " }
|
|
||||||
input #i-carry .i-dur name="carry_prev_month" type="text" placeholder="00:00" {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label #check title="Die Tabelleneinträge werden chronologisch sortiert, anstatt dass ihre Reihenfolge beibehalten wird." {
|
|
||||||
"Einträge sortieren "
|
|
||||||
input name="sort" type="checkbox" value="true" checked {}
|
|
||||||
}
|
|
||||||
|
|
||||||
label #validate title="Die Tabelleneinträge werden auf Konsistenz und Korrektheit überprüft, bevor das Dokument generiert wird." {
|
|
||||||
"Einträge validieren "
|
|
||||||
input name="validate" type="checkbox" value="true" checked {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
div #table {
|
|
||||||
div #task { "Tätigkeit" br; "(Stichwort, Projekt)" }
|
|
||||||
div { "Tag" }
|
|
||||||
div { "Beginn" }
|
|
||||||
div { "Ende" }
|
|
||||||
div { "Pause" }
|
|
||||||
div { "Arbeitszeit" }
|
|
||||||
div { }
|
|
||||||
div { "(hh:mm)" }
|
|
||||||
div { "(hh:mm)" }
|
|
||||||
div { "(hh:mm)" }
|
|
||||||
div { }
|
|
||||||
|
|
||||||
@for _ in 0..22 {
|
|
||||||
div { input .i-task name="task" type="text" {} }
|
|
||||||
div { input .i-day name="day" type="number" placeholder="1" min="1" max="31" {} }
|
|
||||||
div { input .i-dur name="start" type="text" placeholder="12:34" {} }
|
|
||||||
div { input .i-dur name="end" type="text" placeholder="12:34" {} }
|
|
||||||
div { input .i-dur name="rest" type="text" placeholder="00:00" {} }
|
|
||||||
div { select name="note" value="" {
|
|
||||||
option value="" { "Normal" }
|
|
||||||
option value="U" { "Urlaub" }
|
|
||||||
option value="K" { "Krankheit" }
|
|
||||||
option value="F" { "Feiertag" }
|
|
||||||
option value="S" { "Sonstiges" }
|
|
||||||
} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button #submit type="button" { "Arbeitszeitdokumentation generieren" }
|
|
||||||
|
|
||||||
pre #info {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use axum::{
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
Json,
|
Json,
|
||||||
};
|
};
|
||||||
use maud::{html, Markup, PreEscaped};
|
use el::{html::*, Document};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -11,53 +11,76 @@ use crate::{
|
||||||
render::{self, Entry, Note, Timesheet, WorkingArea},
|
render::{self, Entry, Note, Timesheet, WorkingArea},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn get() -> Markup {
|
const LINK_SOURCE: &str = "https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator";
|
||||||
page(
|
|
||||||
html! {
|
|
||||||
style { (PreEscaped(include_str!("tsg.css"))) }
|
|
||||||
script type="module" { (PreEscaped(include_str!("tsg.js"))) }
|
|
||||||
},
|
|
||||||
html! {
|
|
||||||
form #form {
|
|
||||||
h1 {
|
|
||||||
"Arbeitszeitdokumentationsgenerator "
|
|
||||||
a #source href="https://github.com/Garmelon/Arbeitszeitdokumentationsgenerator" { "(source)" }
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
pub async fn get() -> Document {
|
||||||
"Du kannst deine Daten auch in einem "
|
let head = (
|
||||||
a href=".." { "coolen Formular" }
|
style(include_str!("tsg.css")),
|
||||||
" eingeben."
|
script((attr::TypeScript::Module, include_str!("tsg.js"))),
|
||||||
}
|
);
|
||||||
|
|
||||||
p {
|
let body = form((
|
||||||
label for="i-global" { "Global.json" }
|
attr::id("form"),
|
||||||
textarea #i-global name="global" placeholder="{}" {}
|
h1((
|
||||||
}
|
"Arbeitszeitdokumentationsgenerator ",
|
||||||
|
a((attr::id("source"), attr::href(LINK_SOURCE), "(source)")),
|
||||||
|
)),
|
||||||
|
p((
|
||||||
|
"Du kannst deine Daten auch in einem ",
|
||||||
|
a((attr::href(".."), "coolen Formular")),
|
||||||
|
" eingeben.",
|
||||||
|
)),
|
||||||
|
p((
|
||||||
|
label((attr::r#for("i-global"), "Global.json")),
|
||||||
|
textarea((
|
||||||
|
attr::id("i-global"),
|
||||||
|
attr::name("global"),
|
||||||
|
attr::placeholder("{}"),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
p((
|
||||||
|
label((attr::r#for("i-month"), "Month.json")),
|
||||||
|
textarea((
|
||||||
|
attr::id("i-month"),
|
||||||
|
attr::name("month"),
|
||||||
|
attr::placeholder("{}"),
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
p((
|
||||||
|
label((
|
||||||
|
attr::title(concat!(
|
||||||
|
"Die Einträge werden chronologisch sortiert,",
|
||||||
|
" anstatt dass ihre Reihenfolge beibehalten wird."
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::name("sort"),
|
||||||
|
attr::TypeInput::Checkbox,
|
||||||
|
attr::checked(),
|
||||||
|
)),
|
||||||
|
" Einträge sortieren",
|
||||||
|
)),
|
||||||
|
label((
|
||||||
|
attr::title(concat!(
|
||||||
|
"Die Einträge werden auf Konsistenz und Korrektheit überprüft,",
|
||||||
|
" bevor das Dokument generiert wird."
|
||||||
|
)),
|
||||||
|
input((
|
||||||
|
attr::name("validate"),
|
||||||
|
attr::TypeInput::Checkbox,
|
||||||
|
attr::checked(),
|
||||||
|
)),
|
||||||
|
" Einträge validieren",
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
button((
|
||||||
|
attr::id("submit"),
|
||||||
|
attr::TypeButton::Button,
|
||||||
|
"Arbeitszeitdokumentation generieren",
|
||||||
|
)),
|
||||||
|
pre(attr::id("info")),
|
||||||
|
));
|
||||||
|
|
||||||
p {
|
page(head, body)
|
||||||
label for="i-month" { "Month.json" }
|
|
||||||
textarea #i-month name="month" placeholder="{}" {}
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
label title="Die Einträge werden chronologisch sortiert, anstatt dass ihre Reihenfolge beibehalten wird." {
|
|
||||||
input name="sort" type="checkbox" checked {}
|
|
||||||
" Einträge sortieren"
|
|
||||||
}
|
|
||||||
|
|
||||||
label title="Die Einträge werden auf Konsistenz und Korrektheit überprüft, bevor das Dokument generiert wird." {
|
|
||||||
input name="validate" type="checkbox" checked {}
|
|
||||||
" Einträge validieren"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button #submit type="button" { "Arbeitszeitdokumentation generieren" }
|
|
||||||
|
|
||||||
pre #info {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_vacation() -> bool {
|
fn default_vacation() -> bool {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue