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;
+}
+