Tuntien lisääminen
This commit is contained in:
parent
dd41081202
commit
8c00c82258
3 changed files with 196 additions and 3 deletions
20
index.html
20
index.html
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Lukujärjestäjä 0.1</title>
|
||||
<link href="tyyli.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<input id="kumoa" type="button" value="Kumoa">
|
||||
|
@ -37,6 +38,25 @@
|
|||
|
||||
<details class="ruutu" open>
|
||||
<summary>Tunnit</summary>
|
||||
<ul id="tunnit-lista"></ul>
|
||||
<form id="tunnit-uusi">
|
||||
<input id="tunnit-uusi-nimi" type="text" placeholder="tunti" required>
|
||||
<input id="tunnit-uusi-kertaa" type="number" min="1" value="1" required>
|
||||
<label for="tunnit-uusi-kertaa">kertaa viikossa</label>
|
||||
<fieldset>
|
||||
<legend>Luokat</legend>
|
||||
<ul id="tunnit-uusi-luokat" class="valintalista"></ul>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Opettajat</legend>
|
||||
<ul id="tunnit-uusi-opettajat" class="valintalista"></ul>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Tilat</legend>
|
||||
<ul id="tunnit-uusi-tilat" class="valintalista"></ul>
|
||||
</fieldset>
|
||||
<input type="submit" value="+">
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<script src="tietokanta.js"></script>
|
||||
|
|
|
@ -42,6 +42,37 @@ document.getElementById('tilat-uusi').addEventListener('submit', (e) => {
|
|||
}));
|
||||
});
|
||||
|
||||
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);
|
||||
|
@ -59,11 +90,15 @@ function suoritaMuutos(tietokanta, muutos) {
|
|||
// 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
|
||||
const seuraava = document.getElementById(`luokka-${seuraavaId}`);
|
||||
let seuraava = document.getElementById(`luokka-${seuraavaId}`);
|
||||
luokatLista.insertBefore(luoLuokka(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
|
||||
|
@ -72,22 +107,36 @@ function suoritaMuutos(tietokanta, muutos) {
|
|||
);
|
||||
const opettajatLista = document.getElementById('opettajat-lista');
|
||||
// ks. kommentti uuden luokan tapauksessa
|
||||
const seuraava = document.getElementById(`opettaja-${seuraavaId}`);
|
||||
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');
|
||||
const seuraava = document.getElementById(`tila-${seuraavaId}`);
|
||||
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));
|
||||
// TODO: tunti poistettu, muutos
|
||||
} else {
|
||||
throw new Error(`Ei toteutettu ${taulu} ${id} ${vanha} ${uusi}`);
|
||||
}
|
||||
|
@ -154,3 +203,68 @@ function luoTila(id, nimi) {
|
|||
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 `${kertaa}× ${nimi} ${luokat} ${opettajat} ${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;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ const taulut = {
|
|||
luokat: 'luokat',
|
||||
opettajat: 'opettajat',
|
||||
tilat: 'tilat',
|
||||
tunnit: 'tunnit',
|
||||
};
|
||||
|
||||
class Transaktio {
|
||||
|
@ -67,6 +68,29 @@ class Transaktio {
|
|||
});
|
||||
this.taulut.get(taulu).set(id, undefined);
|
||||
}
|
||||
|
||||
suodata(taulu, suodatin) {
|
||||
if (!this.taulut.has(taulu)) {
|
||||
throw new Error(`ei taulua ${taulu}`);
|
||||
}
|
||||
const suodatetut = [];
|
||||
for (const [id, sisältö] of this.taulut.get(taulu)) {
|
||||
// Jos sisältö on undefined, rivi on poistettu, eikä sitä tule ottaa
|
||||
// huomioon suodatettaessa
|
||||
if (sisältö !== undefined && suodatin(sisältö)) {
|
||||
suodatetut.push(id);
|
||||
}
|
||||
}
|
||||
for (const [id, sisältö] of this.tietokanta.taulut.get(taulu)) {
|
||||
// Älä huomio rivejä, jotka löytyvät transaktion tauluista. Ne on
|
||||
// joko käsitelty jo edellisessä silmukassa (jos ne on päivitetty)
|
||||
// tai niitä ei tulisi käsitellä ollenkaan (jos ne on poistettu).
|
||||
if (!this.taulut.get(taulu).has(id) && suodatin(sisältö)) {
|
||||
suodatetut.push(id);
|
||||
}
|
||||
}
|
||||
return suodatetut;
|
||||
}
|
||||
}
|
||||
|
||||
class Tietokanta {
|
||||
|
@ -110,6 +134,41 @@ class Tietokanta {
|
|||
|
||||
// Varmista, että invariantit ovat yhä totta
|
||||
for (const {taulu, id, vanha, uusi} of transaktio.muutokset) {
|
||||
if (uusi === undefined && taulu !== taulut.tunnit) {
|
||||
// Poistettu luokka, opettaja tai tila ei ole tunnin käytössä
|
||||
const roikkuvat = transaktio.suodata(taulut.tunnit, (tunti) => {
|
||||
if (taulu === taulut.luokat) {
|
||||
return tunti.luokat.includes(id);
|
||||
} else if (taulu === taulut.opettajat) {
|
||||
return tunti.opettajat.includes(id);
|
||||
} else if (taulu === taulut.tilat) {
|
||||
return tunti.tilat.includes(id);
|
||||
} else {
|
||||
throw new Error(`Ei-tunnettu taulu ${taulu}`);
|
||||
}
|
||||
});
|
||||
if (roikkuvat.length !== 0) {
|
||||
throw new Error(`Yritetty poistaa ${taulu}:${id}, joka on ${roikkuvat} käytössä`);
|
||||
}
|
||||
} else if (taulu === taulut.tunnit) {
|
||||
// Uusi tunti käyttää vain olemassaolevia luokkia, opettajia ja
|
||||
// tiloja
|
||||
for (const luokka of uusi.luokat) {
|
||||
if (transaktio.hae(taulut.luokat, luokka) === undefined) {
|
||||
throw new Error(`Yritetty luoda tunti ${id} olemattomalla luokalla ${luokka}`);
|
||||
}
|
||||
}
|
||||
for (const opettaja of uusi.opettajat) {
|
||||
if (transaktio.hae(taulut.opettajat, opettaja) === undefined) {
|
||||
throw new Error(`Yritetty luoda tunti ${id} olemattomalla opettajalla ${opettaja}`);
|
||||
}
|
||||
}
|
||||
for (const tila of uusi.tilat) {
|
||||
if (transaktio.hae(taulut.tilat, tila) === undefined) {
|
||||
throw new Error(`Yritetty luoda tunti ${id} olemattomalla tilalla ${tila}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Suorita muutokset
|
||||
|
|
Loading…
Reference in a new issue