From ec1b43754adb26aa26b4d253d87e482141cffaea Mon Sep 17 00:00:00 2001 From: derped Date: Sat, 17 Apr 2021 10:30:52 +0200 Subject: [PATCH] Init: basic templating. --- README.md | 23 +++ berichtsheft/assets/css/notebook.css | 193 +++++++++++++++++++++ berichtsheft/assets/js/notebook.js | 140 +++++++++++++++ berichtsheft/assets/templates/blank.html | 10 ++ berichtsheft/assets/templates/report.html | 197 ++++++++++++++++++++++ berichtsheft/assets/templates/title.html | 22 +++ berichtsheft/index.html | 23 +++ 7 files changed, 608 insertions(+) create mode 100644 README.md create mode 100644 berichtsheft/assets/css/notebook.css create mode 100644 berichtsheft/assets/js/notebook.js create mode 100644 berichtsheft/assets/templates/blank.html create mode 100644 berichtsheft/assets/templates/report.html create mode 100644 berichtsheft/assets/templates/title.html create mode 100644 berichtsheft/index.html diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6513dd --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# 📚 Digitales Berichtsheft +Eine WebApp zur digitalen führung des Berichtshefts. + +## Beweggründe +Ich schreibe nicht gerne von Hand und die Prüfer der IHK bevorzugen mit sicherheit auch ein gut lesbares Dokument. +Alternativen waren entweder umständlich/schwer zugänglich (Word Dokumente) oder hinter einer paywall. + +## Zustand des Projekts +Die meisten Templates und Funktionen zum anzeigen des Berichtshefts sind geschrieben. \ +Aktuell muss man die Berichtsheftdaten noch händisch in das "userdata" objekt einfügen. + +## Feature Roadmap für v1.0 +- [ ] Templates + - [x] Titelseite + - [x] Leer/Platzhalter + - [ ] Fehlzeiten + - [x] Wochenbericht +- [ ] Import & Export von Berichtsheftdaten +- [ ] Session storage +- [ ] Funktionen + - [x] Hinzufügen von Seiten + - [ ] Löschen von Seiten + - [ ] Formulare zum eintragen/modifizieren von Berichtsheftseiten diff --git a/berichtsheft/assets/css/notebook.css b/berichtsheft/assets/css/notebook.css new file mode 100644 index 0000000..4618e25 --- /dev/null +++ b/berichtsheft/assets/css/notebook.css @@ -0,0 +1,193 @@ +body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + background: darkgray; +} + +hr { + border-top: 1px solid black; +} + +td { + height: 1.5em; +} + +table.week { + width: 100%; + height: 80%; +} + +table.week th { + height: 2em; + font-weight: normal; + text-align: center; + vertical-align: middle; + background-color: #f2f2f2; +} + +table.week tbody:nth-child(odd) tr:nth-child(odd) { + background-color: #f2f2f2; +} + +table.week tbody:nth-child(even) tr:nth-child(even) { + background-color: #f2f2f2; +} + +table.week thead th:nth-last-child(-n+2) { + width: 10%; + font-size: 80%; +} + +table.week td:nth-last-child(-n+2) { + text-align: center; +} + +table.week tbody:last-child tr:last-child td:first-child { + text-align: right; +} + +.vtable { + width: 1em; +} + +.vertical { + vertical-align: middle; + writing-mode: vertical-lr; + transform: rotate(180deg); +} + +.sign { + position: absolute; + bottom: 0; + width: 100%; + height: 15%; +} + +.sign table { + width: 100%; + height: 100%; +} + +.sign table, .sign table td { + border: 1px solid black; + border-collapse: collapse; +} + +.sign td { + width: 50%; +} + +.sign tr:last-child td { + height: 90%; + text-align: center; + vertical-align: bottom; + font-size: 0.7em; +} + +.page { + position: relative; + margin: auto; + margin-bottom: 0.25cm; + width: 21cm; + height: 29.7cm; + display: grid; + grid-template-rows: 2cm auto 2cm; + background: white; +} + +.page:nth-child(odd) { + grid-template-columns: 2.41cm auto 0.81cm; +} + +.page:nth-child(even) { + grid-template-columns: 0.81cm auto 2.42cm; +} + +.pg-head { + position: relative; + width: 100%; + height: 100%; + grid-row: 1 / 2; + grid-column: 2 / 3; + background: white; +} + +.pg-head .flex { + position: absolute; + top: 1cm; + text-align: center; +} + +.pg-head img { + position: absolute; + top: .5cm; + height: .5cm; +} + +.page:nth-child(odd) .pg-head img { + right: 0; +} + +.pg-content { + position: relative; + width: 100%; + height: 100%; + grid-row: 2 / 3; + grid-column: 2 / 3; +} + +.pg-footer { + position: relative; + width: 100%; + height: 100%; + grid-row: 3 / 4; + grid-column: 2 / 3; + display: flex; + justify-content: center; + align-items: center; + white-space: pre; +} + +div.sticky { + position: sticky; + position: -webkit-sticky; + align-self: flex-start; + top: 0; +} + +.flex { + width: 100%; + display: flex; + white-space: pre; +} + +.eightyw { + width: 80%; +} + +.halfw { + width: 50%; +} + +.quarterw { + width: 25%; +} + +.tenw { + width: 10%; +} + +.halfh { + height: 50%; +} + +@media print { + body, .page { + margin: none; + } + .sticky, button { + display: none; + } +} diff --git a/berichtsheft/assets/js/notebook.js b/berichtsheft/assets/js/notebook.js new file mode 100644 index 0000000..88df914 --- /dev/null +++ b/berichtsheft/assets/js/notebook.js @@ -0,0 +1,140 @@ +"use strict"; + +const app = document.getElementById("appContent"); +let userdata; +load(); +const emptyPages = { + "title": {"type": "title"}, + "blank": {"type": "blank"}, + "report": { + "type": "report", + "days": [ [], [], [], [], [], ], + }, + +}; +let templates; + +// const templates = { +// "blank": (await fetchTemplate("blank")) +// }; +// let blank = fetchTemplate("blank").then(b=>{blank=b}); +// let blank = fetchTemplate("blank") +async function init() { + if (typeof templates === "undefined") { + templates = { + "title": await fetchTemplate("title"), + "blank": await fetchTemplate("blank"), + "report": await fetchTemplate("report"), + }; + } + [...app.children].forEach(child => app.removeChild(child)) + + userdata.pages.forEach((e,i) => { + pageAdd(e.type); + populate(i+1); + }) +} + +function pageAdd(template) { + pageNew(template); + populate(app.children.length); +} + +function pageNew(template) { + const node = templates[template].content.cloneNode(true); + node.children[0].id = `Page-${app.children.length+1}`; + app.appendChild(node); + fixPageCount(); + userdata.pages.push(emptyPages[template]) +} + +function populate(pnum) { + if (pnum > 0 && pnum <= app.children.length <= userdata.pages.length) { + const node = app.children[pnum-1]; + const data = userdata.pages[pnum-1]; + node.querySelectorAll(".logo").forEach(i=>i.src = userdata.meta.logo); + if (node.classList.contains(data.type)) { + switch (data.type) { + case "report": + let startDate = data.start; + if (typeof startDate === "undefined") { + const dates = (pnum > 1) && app.children[pnum-2].getElementsByClassName("date") || []; + startDate = dates.length > 1 && dates[1].textContent.split(".").reverse().map(Number) || undefined + if (typeof startDate === "undefined") { + startDate = userdata.meta.start || [0,0,0]; + } else { + startDate[1] -= 1; + startDate[2] += 3; + } + } + let endDate = data.end; + if (typeof endDate === "undefined") { + endDate = [...startDate]; + endDate[2] += 4; + } + const date = node.querySelectorAll(".date"); + date[0].textContent = getDate(startDate); + date[1].textContent = getDate(endDate); + + const week = node.getElementsByClassName("week")[0].querySelectorAll(".day"); + let weekh = null; + for (let i=0; i < week.length && i < data.days.length; i++) { + let day = week[i].children; + let dayh = null; + for (let j=0; j < day.length && j < data.days[i].length; j++) { + day[j].querySelectorAll("td")[0].textContent = data.days[i][j][0]; + day[j].querySelectorAll("td")[1].textContent = data.days[i][j][1]; + dayh += data.days[i][j][1]; + } + day[day.length-1].querySelector(".subtotal").textContent = dayh; + weekh += dayh; + } node.querySelector(".total").textContent = weekh; + + case "blank": + node.querySelector(".pnum").textContent = pnum; + break; + case "title": + let tdate = node.querySelectorAll(".tdate"); + tdate[0].textContent = getDate(userdata.meta.start); + tdate[1].textContent = getDate(userdata.meta.end); + node.querySelector(".name").textContent = `${userdata.meta.lastName}, ${userdata.meta.firstName}`; + break; + } + } + } +} + +function getDate(date) { + let d = date && new Date(...date) || new Date(); + return `${String(d.getDate()).padStart(2, "0")}.${String(d.getMonth()+1).padStart(2, "0")}.${d.getFullYear()}` +} + +function fixPageCount() { + const pc = document.getElementsByClassName("pcount"); + for (let i=0; i < pc.length; i++) { + pc[i].textContent = app.children.length; + } +} + +async function fetchTemplate(tname) { + let template = document.createElement("template"); + template.innerHTML = await ( await fetch(`assets/templates/${tname}.html`)).text(); + return template.content.getElementById(tname); +} + +function load() { +userdata = JSON.parse(localStorage.getItem("userdata")) || + { "meta": { + "firstName": "", + "lastName": "", + "start": null, + "end": null, + "logo": "" + }, + "pages": [], + }; +} + +function save() { + localStorage.setItem("userdata", JSON.stringify(userdata)) +} diff --git a/berichtsheft/assets/templates/blank.html b/berichtsheft/assets/templates/blank.html new file mode 100644 index 0000000..9f13001 --- /dev/null +++ b/berichtsheft/assets/templates/blank.html @@ -0,0 +1,10 @@ + diff --git a/berichtsheft/assets/templates/report.html b/berichtsheft/assets/templates/report.html new file mode 100644 index 0000000..9a3ad4d --- /dev/null +++ b/berichtsheft/assets/templates/report.html @@ -0,0 +1,197 @@ + diff --git a/berichtsheft/assets/templates/title.html b/berichtsheft/assets/templates/title.html new file mode 100644 index 0000000..adf8650 --- /dev/null +++ b/berichtsheft/assets/templates/title.html @@ -0,0 +1,22 @@ + diff --git a/berichtsheft/index.html b/berichtsheft/index.html new file mode 100644 index 0000000..d5f02b0 --- /dev/null +++ b/berichtsheft/index.html @@ -0,0 +1,23 @@ + + + + + + + + Mein Berichtsheft + + +
+ + + +
+ +
+ + +