lukujarjestaja/käyttöliittymä.js

281 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
document.getElementById('kumoa').addEventListener('click', () => {
suorita(_tietokanta.kumoa());
});
document.getElementById('luokat-uusi').addEventListener('submit', (e) => {
e.preventDefault();
suorita(_tietokanta.transaktio((t) => {
const luokanNimi = document.getElementById('luokat-uusi-nimi').value;
t.lisää(taulut.luokat, luokanNimi)
document.getElementById('luokat-uusi-nimi').value = '';
}));
});
document.getElementById('opettajat-uusi').addEventListener('submit', (e) => {
e.preventDefault();
suorita(_tietokanta.transaktio((t) => {
const nimi = document.getElementById('opettajat-uusi-nimi').value;
const lyhenne = document.getElementById('opettajat-uusi-lyhenne').value;
t.lisää(taulut.opettajat, {nimi, lyhenne});
document.getElementById('opettajat-uusi-nimi').value = '';
document.getElementById('opettajat-uusi-lyhenne').value = '';
}));
});
document.getElementById('opettajat-uusi-nimi').addEventListener('change', () => {
const nimi = document.getElementById('opettajat-uusi-nimi').value;
// TODO: Kunnollinen tuki grafeemiklustereille
// TODO: Älä ehdota lyhennettä, joka on jo käytössä
const lyhenne = nimi.split(' ')
.map((x) => String.fromCodePoint(x.codePointAt(0))).join('');
document.getElementById('opettajat-uusi-lyhenne').value = lyhenne;
});
document.getElementById('tilat-uusi').addEventListener('submit', (e) => {
e.preventDefault();
suorita(_tietokanta.transaktio((t) => {
const tilanNimi = document.getElementById('tilat-uusi-nimi').value;
t.lisää(taulut.tilat, tilanNimi)
document.getElementById('tilat-uusi-nimi').value = '';
}));
});
document.getElementById('tunnit-uusi').addEventListener('submit', (e) => {
e.preventDefault();
suorita(_tietokanta.transaktio((t) => {
const nimi = document.getElementById('tunnit-uusi-nimi').value;
const kertaa =
Number.parseInt(document.getElementById('tunnit-uusi-kertaa').value);
const luokat = valitutHTMLLuokalla('tunnit-uusi-luokka');
const opettajat = valitutHTMLLuokalla('tunnit-uusi-opettaja');
const tilat = valitutHTMLLuokalla('tunnit-uusi-tila');
t.lisää(taulut.tunnit, {
nimi, luokat, opettajat, tilat,
milloin: new Array(kertaa),
});
document.getElementById('tunnit-uusi-nimi').value = '';
document.getElementById('tunnit-uusi-kertaa').value = 1;
for (const valinta of document.getElementsByClassName('tunnit-uusi-valinta')) {
valinta.checked = false;
}
}));
});
function valitutHTMLLuokalla(htmlLuokka) {
const valitut = [];
for (const valinta of document.getElementsByClassName(htmlLuokka)) {
if (valinta.checked) {
valitut.push(Number.parseInt(valinta.value));
}
}
return valitut;
}
function suorita([tietokanta, muutokset]) {
for (const muutos of muutokset) {
suoritaMuutos(tietokanta, muutos);
}
tallennaTietokanta(tietokanta);
}
function suoritaMuutos(tietokanta, muutos) {
const {taulu, id, vanha, uusi} = muutos;
if (taulu === taulut.luokat && vanha === undefined) {
// Uusi luokka
const seuraavaId = idJälkeen(tietokanta, taulu, id, vertaa);
const luokatLista = document.getElementById('luokat-lista');
// getElementById palauttaa null:n, jos id:tä ei löydy. Jos tämä luokka
// on viimeinen, seuraavaId on undefined, eikä DOM:ssa ole luokkaa
// "luokka-undefined". seuraava on siis null silloin kuin tämä luokka
// tulee lisätä listan loppuun, joka vastaa insertBefore:n toimintaa
let seuraava = document.getElementById(`luokka-${seuraavaId}`);
luokatLista.insertBefore(luoLuokka(tietokanta, id, uusi), seuraava);
const tunnitUusiLuokat = document.getElementById('tunnit-uusi-luokat');
seuraava = document.getElementById(`tunnit-uusi-luokka-${seuraavaId}`);
tunnitUusiLuokat.insertBefore(luoLuokkaValinta(id, uusi), seuraava);
} else if (taulu === taulut.luokat && uusi === undefined) {
// Luokka poistettu
poistaElementti(document.getElementById(`luokka-${id}`));
poistaElementti(document.getElementById(`tunnit-uusi-luokka-${id}`));
// TODO: luokka muutos
} else if (taulu === taulut.opettajat && vanha === undefined) {
// Uusi opettaja
const seuraavaId = idJälkeen(tietokanta, taulu, id,
(a, b) => vertaa(a.nimi, b.nimi)
);
const opettajatLista = document.getElementById('opettajat-lista');
// ks. kommentti uuden luokan tapauksessa
let seuraava = document.getElementById(`opettaja-${seuraavaId}`);
opettajatLista.insertBefore(luoOpettaja(id, uusi), seuraava);
const tunnitUusiOpettajat = document.getElementById('tunnit-uusi-opettajat');
seuraava = document.getElementById(`tunnit-uusi-opettaja-${seuraavaId}`);
tunnitUusiOpettajat.insertBefore(luoOpettajaValinta(id, uusi), seuraava);
} else if (taulu === taulut.opettajat && uusi === undefined) {
// Opettaja poistettu
poistaElementti(document.getElementById(`opettaja-${id}`));
poistaElementti(document.getElementById(`tunnit-uusi-opettaja-${id}`));
// TODO: opettaja muutos
} else if (taulu === taulut.tilat && vanha === undefined) {
// Uusi tila
const seuraavaId = idJälkeen(tietokanta, taulu, id, vertaa);
const tilatLista = document.getElementById('tilat-lista');
let seuraava = document.getElementById(`tila-${seuraavaId}`);
tilatLista.insertBefore(luoTila(id, uusi), seuraava);
const tunnitUusiTilat = document.getElementById(`tunnit-uusi-tilat`);
seuraava = document.getElementById(`tunnit-uusi-tila-${seuraavaId}`);
tunnitUusiTilat.insertBefore(luoTilaValinta(id, uusi), seuraava);
} else if (taulu === taulut.tilat && uusi === undefined) {
// Tila poistettu
poistaElementti(document.getElementById(`tila-${id}`));
poistaElementti(document.getElementById(`tunnit-uusi-tila-${id}`));
// TODO: tila muutos
} else if (taulu === taulut.tunnit && vanha === undefined) {
// Uusi tunti
// TODO: Järjestys
const tunnitLista = document.getElementById('tunnit-lista');
tunnitLista.appendChild(luoTunti(tietokanta, id, uusi));
} else if (taulu === taulut.tunnit && uusi === undefined) {
poistaElementti(document.getElementById(`tunti-${id}`));
// TODO: tunti muutos
} else {
throw new Error(`Ei toteutettu ${taulu} ${id} ${vanha} ${uusi}`);
}
}
function idJälkeen(tietokanta, taulu, id, vertaa) {
const järjestys = tietokanta.järjestyksessä(taulu, vertaa);
return järjestys[järjestys.indexOf(id) + 1];
}
function vertaa(a, b) {
// TODO: Parempi vertailufunktio?
return a.localeCompare(b);
}
function poistaElementti(elementti) {
elementti.parentElement.removeChild(elementti);
}
function luoLuokka(tietokanta, id, nimi) {
const li = document.createElement('li');
li.id = `luokka-${id}`;
const poistoPainike = document.createElement('input');
poistoPainike.type = 'button';
poistoPainike.value = '-';
poistoPainike.addEventListener('click', () => {
suorita(_tietokanta.transaktio((t) => {
const käyttävät =
t.suodata(taulut.tunnit, (tunti) => tunti.luokat.includes(id))
.map((x) => tuntiTeksti(tietokanta, t.hae(taulut.tunnit, x)));
if (käyttävät.length === 0) {
t.poista(taulut.luokat, id);
} else {
const lista = käyttävät.join('\n- ');
alert(`Ei voida poistaa ennen tunteja:\n- ${lista}`);
}
}));
});
li.appendChild(poistoPainike);
li.appendChild(document.createTextNode(nimi));
return li;
}
function luoOpettaja(id, {nimi, lyhenne}) {
const li = document.createElement('li');
li.id = `opettaja-${id}`;
const poistoPainike = document.createElement('input');
poistoPainike.type = 'button';
poistoPainike.value = '-';
poistoPainike.addEventListener('click', () => {
suorita(_tietokanta.transaktio((t) => {
t.poista(taulut.opettajat, id);
}));
});
li.appendChild(poistoPainike);
li.appendChild(document.createTextNode(`${nimi} (${lyhenne})`));
return li;
}
function luoTila(id, nimi) {
const li = document.createElement('li');
li.id = `tila-${id}`;
const poistoPainike = document.createElement('input');
poistoPainike.type = 'button';
poistoPainike.value = '-';
poistoPainike.addEventListener('click', () => {
suorita(_tietokanta.transaktio((t) => {
t.poista(taulut.tilat, id);
}));
});
li.appendChild(poistoPainike);
li.appendChild(document.createTextNode(nimi));
return li;
}
function luoTunti(tietokanta, id, tunti) {
const li = document.createElement('li');
li.id = `tunti-${id}`;
const poistoPainike = document.createElement('input');
poistoPainike.type = 'button';
poistoPainike.value = '-';
poistoPainike.addEventListener('click', () => {
suorita(_tietokanta.transaktio((t) => {
t.poista(taulut.tunnit, id);
}));
});
li.appendChild(poistoPainike);
li.appendChild(document.createTextNode(tuntiTeksti(tietokanta, tunti)));
return li;
}
function tuntiTeksti(tietokanta, tunti) {
const kertaa = tunti.milloin.length;
const nimi = tunti.nimi;
const luokat = tunti.luokat.map((x) => tietokanta.hae(taulut.luokat, x));
const opettajat = tunti.opettajat
.map((x) => tietokanta.hae(taulut.opettajat, x).lyhenne);
const tilat = tunti.tilat.map((x) => tietokanta.hae(taulut.tilat, x));
return `${luokat} ${opettajat} ${kertaa}×${nimi} tilassa ${tilat}`;
}
function luoLuokkaValinta(id, nimi) {
const li = document.createElement('li');
li.id = `tunnit-uusi-luokka-${id}`;
const valinta = document.createElement('input');
valinta.type = 'checkbox';
valinta.classList.add('tunnit-uusi-valinta');
valinta.classList.add('tunnit-uusi-luokka');
valinta.value = id;
li.appendChild(valinta);
li.appendChild(document.createTextNode(nimi));
return li;
}
function luoOpettajaValinta(id, {nimi, lyhenne}) {
const li = document.createElement('li');
li.id = `tunnit-uusi-opettaja-${id}`;
const valinta = document.createElement('input');
valinta.type = 'checkbox';
valinta.classList.add('tunnit-uusi-valinta');
valinta.classList.add('tunnit-uusi-opettaja');
valinta.value = id;
li.appendChild(valinta);
li.appendChild(document.createTextNode(`${nimi} (${lyhenne})`));
return li;
}
function luoTilaValinta(id, nimi) {
const li = document.createElement('li');
li.id = `tunnit-uusi-tila-${id}`;
const valinta = document.createElement('input');
valinta.type = 'checkbox';
valinta.classList.add('tunnit-uusi-valinta');
valinta.classList.add('tunnit-uusi-tila');
valinta.value = id;
li.appendChild(valinta);
li.appendChild(document.createTextNode(nimi));
return li;
}