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>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Lukujärjestäjä 0.1</title>
|
<title>Lukujärjestäjä 0.1</title>
|
||||||
|
<link href="tyyli.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<input id="kumoa" type="button" value="Kumoa">
|
<input id="kumoa" type="button" value="Kumoa">
|
||||||
|
@ -37,6 +38,25 @@
|
||||||
|
|
||||||
<details class="ruutu" open>
|
<details class="ruutu" open>
|
||||||
<summary>Tunnit</summary>
|
<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>
|
</details>
|
||||||
|
|
||||||
<script src="tietokanta.js"></script>
|
<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]) {
|
function suorita([tietokanta, muutokset]) {
|
||||||
for (const muutos of muutokset) {
|
for (const muutos of muutokset) {
|
||||||
suoritaMuutos(tietokanta, muutos);
|
suoritaMuutos(tietokanta, muutos);
|
||||||
|
@ -59,11 +90,15 @@ function suoritaMuutos(tietokanta, muutos) {
|
||||||
// on viimeinen, seuraavaId on undefined, eikä DOM:ssa ole luokkaa
|
// on viimeinen, seuraavaId on undefined, eikä DOM:ssa ole luokkaa
|
||||||
// "luokka-undefined". seuraava on siis null silloin kuin tämä luokka
|
// "luokka-undefined". seuraava on siis null silloin kuin tämä luokka
|
||||||
// tulee lisätä listan loppuun, joka vastaa insertBefore:n toimintaa
|
// 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);
|
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) {
|
} else if (taulu === taulut.luokat && uusi === undefined) {
|
||||||
// Luokka poistettu
|
// Luokka poistettu
|
||||||
poistaElementti(document.getElementById(`luokka-${id}`));
|
poistaElementti(document.getElementById(`luokka-${id}`));
|
||||||
|
poistaElementti(document.getElementById(`tunnit-uusi-luokka-${id}`));
|
||||||
// TODO: luokka muutos
|
// TODO: luokka muutos
|
||||||
} else if (taulu === taulut.opettajat && vanha === undefined) {
|
} else if (taulu === taulut.opettajat && vanha === undefined) {
|
||||||
// Uusi opettaja
|
// Uusi opettaja
|
||||||
|
@ -72,22 +107,36 @@ function suoritaMuutos(tietokanta, muutos) {
|
||||||
);
|
);
|
||||||
const opettajatLista = document.getElementById('opettajat-lista');
|
const opettajatLista = document.getElementById('opettajat-lista');
|
||||||
// ks. kommentti uuden luokan tapauksessa
|
// ks. kommentti uuden luokan tapauksessa
|
||||||
const seuraava = document.getElementById(`opettaja-${seuraavaId}`);
|
let seuraava = document.getElementById(`opettaja-${seuraavaId}`);
|
||||||
opettajatLista.insertBefore(luoOpettaja(id, uusi), seuraava);
|
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) {
|
} else if (taulu === taulut.opettajat && uusi === undefined) {
|
||||||
// Opettaja poistettu
|
// Opettaja poistettu
|
||||||
poistaElementti(document.getElementById(`opettaja-${id}`));
|
poistaElementti(document.getElementById(`opettaja-${id}`));
|
||||||
|
poistaElementti(document.getElementById(`tunnit-uusi-opettaja-${id}`));
|
||||||
// TODO: opettaja muutos
|
// TODO: opettaja muutos
|
||||||
} else if (taulu === taulut.tilat && vanha === undefined) {
|
} else if (taulu === taulut.tilat && vanha === undefined) {
|
||||||
// Uusi tila
|
// Uusi tila
|
||||||
const seuraavaId = idJälkeen(tietokanta, taulu, id, vertaa);
|
const seuraavaId = idJälkeen(tietokanta, taulu, id, vertaa);
|
||||||
const tilatLista = document.getElementById('tilat-lista');
|
const tilatLista = document.getElementById('tilat-lista');
|
||||||
const seuraava = document.getElementById(`tila-${seuraavaId}`);
|
let seuraava = document.getElementById(`tila-${seuraavaId}`);
|
||||||
tilatLista.insertBefore(luoTila(id, uusi), seuraava);
|
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) {
|
} else if (taulu === taulut.tilat && uusi === undefined) {
|
||||||
// Tila poistettu
|
// Tila poistettu
|
||||||
poistaElementti(document.getElementById(`tila-${id}`));
|
poistaElementti(document.getElementById(`tila-${id}`));
|
||||||
|
poistaElementti(document.getElementById(`tunnit-uusi-tila-${id}`));
|
||||||
// TODO: tila muutos
|
// 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 {
|
} else {
|
||||||
throw new Error(`Ei toteutettu ${taulu} ${id} ${vanha} ${uusi}`);
|
throw new Error(`Ei toteutettu ${taulu} ${id} ${vanha} ${uusi}`);
|
||||||
}
|
}
|
||||||
|
@ -154,3 +203,68 @@ function luoTila(id, nimi) {
|
||||||
li.appendChild(document.createTextNode(nimi));
|
li.appendChild(document.createTextNode(nimi));
|
||||||
return li;
|
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',
|
luokat: 'luokat',
|
||||||
opettajat: 'opettajat',
|
opettajat: 'opettajat',
|
||||||
tilat: 'tilat',
|
tilat: 'tilat',
|
||||||
|
tunnit: 'tunnit',
|
||||||
};
|
};
|
||||||
|
|
||||||
class Transaktio {
|
class Transaktio {
|
||||||
|
@ -67,6 +68,29 @@ class Transaktio {
|
||||||
});
|
});
|
||||||
this.taulut.get(taulu).set(id, undefined);
|
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 {
|
class Tietokanta {
|
||||||
|
@ -110,6 +134,41 @@ class Tietokanta {
|
||||||
|
|
||||||
// Varmista, että invariantit ovat yhä totta
|
// Varmista, että invariantit ovat yhä totta
|
||||||
for (const {taulu, id, vanha, uusi} of transaktio.muutokset) {
|
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
|
// Suorita muutokset
|
||||||
|
|
Loading…
Reference in a new issue