diff --git a/flake.nix b/flake.nix index a722d8c..c469a92 100644 --- a/flake.nix +++ b/flake.nix @@ -13,6 +13,7 @@ just toml2json nodePackages.webpack-cli + entr typescript typescript-language-server diff --git a/justfile b/justfile index a5e9289..b2628b3 100644 --- a/justfile +++ b/justfile @@ -4,15 +4,21 @@ alias c := clean build: mkdir -p build - cat src/data/* | toml2json > build/gewichtungen.json + cat ./src/studiengänge/* | toml2json > build/studiengaenge.json # typescript compilation depends on gewichtungen.json tsc mv src/rechner.js build/ + # This makes the code more debuggable which is a win in my book webpack --mode development - cp src/index.html dist/index.html + cp src/index.html src/stylesheet.css dist/ + cp ./res/Exo2-VariableFont_wght.ttf dist/ + +watch: + find src/ | entr -s 'just build' clean: rm -rf ./build ./dist + rm ./src/rechner.js diff --git a/res/Exo2-VariableFont_wght.ttf b/res/Exo2-VariableFont_wght.ttf new file mode 100644 index 0000000..fb08481 Binary files /dev/null and b/res/Exo2-VariableFont_wght.ttf differ diff --git a/src/index.html b/src/index.html index 6aaedfc..65cd5a8 100644 --- a/src/index.html +++ b/src/index.html @@ -21,18 +21,26 @@ along with this program. If not, see . iFSR Notenrechner + + +

Notenberechnungen

Hier könnt ihr Vordiploms- und Abschlussnoten ausgewählter Studiengänge der Fakultät Informatik der TU Dresden berechnen.

- - +
+ +
+ + +
-
-
+
+
+
diff --git a/src/rechner.ts b/src/rechner.ts index 5c1a15b..407fac4 100644 --- a/src/rechner.ts +++ b/src/rechner.ts @@ -14,14 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -import gewichtungen from '../build/gewichtungen.json' +import studiengaenge from '../build/studiengaenge.json' -var select = document.getElementById("options") as HTMLSelectElement; +var select = document.getElementById("studiengaenge") as HTMLSelectElement; -for (let key in gewichtungen) { +for (let key in studiengaenge) { let option = document.createElement('option'); option.value = key; - option.text = String(gewichtungen[key as keyof typeof gewichtungen].display_name); + option.text = String(studiengaenge[key as keyof typeof studiengaenge].display_name); select.add(option); } select.selectedIndex = 0; @@ -30,10 +30,11 @@ var noten = document.getElementById("noten") as HTMLFormElement; select.onchange = function changed() { noten.innerHTML = ""; - let gewichtung_index = select.selectedOptions[0].value as keyof typeof gewichtungen; - let gewichtung = gewichtungen[gewichtung_index]; + let gewichtung_index = select.selectedOptions[0].value as keyof typeof studiengaenge; + let gewichtung = studiengaenge[gewichtung_index]; let table = document.createElement('table'); + for (let modulIndex in gewichtung.module) { let modul = gewichtung.module[modulIndex]; let label = document.createElement('label'); @@ -46,7 +47,6 @@ select.onchange = function changed() { input.required = true; input.min = "1"; input.max = "5"; - input.style.width = "70px"; input.step = "0.1"; input.addEventListener("input", () => { // Validate with the built-in constraints @@ -60,6 +60,7 @@ select.onchange = function changed() { input.setCustomValidity("Keine Berechnung möglich bei nicht bestandenen Prüfungen (mit > 4.0)") } }); + input.className = "noteninput"; label.htmlFor = input.id; label.textContent = modul.name; @@ -69,9 +70,9 @@ select.onchange = function changed() { } noten.appendChild(table); - let submit = document.createElement('button'); + let submit = document.createElement('input'); submit.type = "submit"; - submit.innerText = "Berechnen"; + submit.value = "Berechnen"; let result = document.createElement('p'); diff --git a/src/data/ba_inf_2009.toml b/src/studiengänge/ba_inf_2009.toml similarity index 100% rename from src/data/ba_inf_2009.toml rename to src/studiengänge/ba_inf_2009.toml diff --git a/src/stylesheet.css b/src/stylesheet.css new file mode 100644 index 0000000..2e3051f --- /dev/null +++ b/src/stylesheet.css @@ -0,0 +1,157 @@ +@font-face { + font-family: "Exo 2"; + src: url(./Exo2-VariableFont_wght.ttf) format("truetype"); +} + +:root { + --base1: rgb(40, 43, 40); + --base2: rgb(60, 63, 60); + --base3: rgb(137, 141, 137); + --base4: rgb(215, 220, 215); + --base5: rgb(235, 240, 235); + + --accent1: rgb(177, 255, 28); + --accent2: rgb(156, 214, 24); + --signal: rgb(225, 177, 28); + --gray: rgb(137, 141, 137); + + --text: var(--base1); + --bg: var(--base5); + --border: var(--base2); +} + +@media (prefers-color-scheme: dark) { + :root { + --text: var(--base5); + --bg: var(--base1); + --border: var(--base3); + }; +} + +html * { + font-family: "Exo 2", sans-serif; + background-color: var(--bg); + color: var(--text); +} + +h1 { + font-size: 24pt; + font-weight: bolder; +} + +#notenform { + align-items: center; + display: flex; + flex-direction: column; +} + +table { + border-collapse: collapse; + margin: 8px 0; + width: fill; + max-width: 1200px; +} + +th, td { + border-top: 1px dotted black; + border-bottom: 1px dotted black; + padding: 8px 0; +} + +input { + outline: none; + padding: 4px; + border: 2px solid var(--border); +} + +input:focus { + border: 2px solid var(--accent1); +} + +#noten { + display: flex; + flex-direction: column; +} + +input[type=submit] { + align-self: end; + margin: 8px; + width: 76px; + box-sizing: border-box; +} + +label { + margin: 8px; +} + +.noteninput { + margin: 0 8px; + border-radius: 2px; + width: 70px; +} + +/* remove the spin buttons */ +input::-webkit-inner-spin-button, +input::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} +input[type=number] { + -moz-appearance: textfield; +} + + +select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: transparent; + border: none; + padding: 4px; + width: 100%; + font-family: inherit; + font-size: inherit; + cursor: inherit; + line-height: inherit; + z-index: 1; + outline: none; +} +select::-ms-expand { + display: none; +} + +.select { + display: grid; + grid-template-areas: "select"; + align-items: center; + position: relative; + min-width: 15ch; + max-width: 30ch; + border: 1px solid var(--border); + border-radius: 2px; + cursor: pointer; +} +.select select, .select::after { + grid-area: select; +} +.select::after { + content: ""; + justify-self: end; + width: 0.8em; + height: 0.5em; + margin-right: 4px; + background-color: var(--accent1); + -webkit-clip-path: polygon(100% 0%, 0 0%, 50% 100%); + clip-path: polygon(100% 0%, 0 0%, 50% 100%); +} + +select:focus + .focus { + position: absolute; + top: -1px; + left: -1px; + right: -1px; + bottom: -1px; + border: 2px solid var(--accent1); + border-radius: inherit; +} +