diff --git a/index.html b/index.html
index 82d4a13..0f1aad3 100644
--- a/index.html
+++ b/index.html
@@ -69,6 +69,8 @@
+
+
diff --git a/käyttöliittymä.js b/käyttöliittymä.js
index 67eecfb..ef2dc86 100644
--- a/käyttöliittymä.js
+++ b/käyttöliittymä.js
@@ -53,7 +53,7 @@ document.getElementById('tunnit-uusi').addEventListener('submit', (e) => {
const tilat = valitutHTMLLuokalla('tunnit-uusi-tila');
t.lisää(taulut.tunnit, {
nimi, luokat, opettajat, tilat,
- milloin: new Array(kertaa),
+ milloin: new Array(kertaa).fill(null),
});
document.getElementById('tunnit-uusi-nimi').value = '';
document.getElementById('tunnit-uusi-kertaa').value = 1;
@@ -63,6 +63,43 @@ document.getElementById('tunnit-uusi').addEventListener('submit', (e) => {
}));
});
+document.getElementById('lukkari-valinta').addEventListener('input', () => {
+ päivitäLukkari();
+});
+
+let raahattava;
+document.addEventListener('dragstart', (e) => {
+ raahattava = e.target;
+});
+
+function teePudotuskohteeksi(elementti) {
+ elementti.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ });
+
+ elementti.addEventListener('drop', (e) => {
+ e.preventDefault();
+ const raahattavaId = ilmanPrefiksiä('lukkari-tunti-', raahattava.id);
+ const [tunti, toteutus] = raahattavaId.split('-').map((x) => Number.parseInt(x));
+ // XXX: Transaktio ja suoritus
+ if (elementti.id !== 'sijoittamattomat') {
+ const kohdeId = ilmanPrefiksiä('lukkari-solu-', elementti.id);
+ const ajoitus = kohdeId.split('-').map((x) => Number.parseInt(x));
+ _tietokanta.hae(taulut.tunnit, tunti).milloin[toteutus] = ajoitus;
+ } else {
+ _tietokanta.hae(taulut.tunnit, tunti).milloin[toteutus] = null;
+ }
+ päivitäLukkari();
+ });
+}
+
+function ilmanPrefiksiä(prefiksi, teksti) {
+ if (!teksti.startsWith(prefiksi)) {
+ throw new Error(`"${teksti}" ei ala prefiksillä "${prefiksi}"`);
+ }
+ return teksti.slice(prefiksi.length);
+}
+
function valitutHTMLLuokalla(htmlLuokka) {
const valitut = [];
for (const valinta of document.getElementsByClassName(htmlLuokka)) {
@@ -78,6 +115,7 @@ function suorita([tietokanta, muutokset]) {
suoritaMuutos(tietokanta, muutos);
}
tallennaTietokanta(tietokanta);
+ päivitäLukkari();
}
function suoritaMuutos(tietokanta, muutos) {
@@ -147,11 +185,11 @@ function suoritaMuutos(tietokanta, muutos) {
} else if (taulu === taulut.tunnit && vanha === undefined) {
// Uusi tunti
const seuraavaId = idJälkeen(tietokanta, taulu, id,
- (a, b) => vertaa(a.nimi, b.nimi)
+ (a, b) => vertaa(tuntiTeksti(tietokanta, a), tuntiTeksti(tietokanta, b))
);
const tunnitLista = document.getElementById('tunnit-lista');
// ks. kommentti uuden luokan tapauksessa
- const seuraava = document.getElementById(`tunti-${id}`);
+ const seuraava = document.getElementById(`tunti-${seuraavaId}`);
tunnitLista.insertBefore(luoTunti(tietokanta, id, uusi), seuraava);
} else if (taulu === taulut.tunnit && uusi === undefined) {
poistaElementti(document.getElementById(`tunti-${id}`));
@@ -335,3 +373,83 @@ function luoTilaVaihtoehto(id, nimi) {
option.appendChild(document.createTextNode(nimi));
return option;
}
+
+let päivät = ['ma', 'ti', 'ke', 'to', 'pe'];
+let ajat = ['8', '9', '10', '11', '12', '13', '14', '15'];
+
+function päivitäLukkari() {
+ const taulukko = document.createElement('table');
+ taulukko.id = 'lukkari';
+ const taulukonOtsikko = document.createElement('caption');
+ taulukko.appendChild(taulukonOtsikko);
+ const rivit = document.createElement('tbody');
+ const otsikkoRivi = document.createElement('tr');
+ otsikkoRivi.appendChild(document.createElement('td'));
+ for (const päivä of päivät) {
+ const otsikko = document.createElement('th');
+ otsikko.appendChild(document.createTextNode(päivä));
+ otsikkoRivi.appendChild(otsikko);
+ }
+ rivit.appendChild(otsikkoRivi);
+ for (const [aikaId, aika] of numeroi(ajat)) {
+ const rivi = document.createElement('tr');
+ const otsikko = document.createElement('th');
+ otsikko.appendChild(document.createTextNode(aika));
+ rivi.appendChild(otsikko);
+ for (const [päiväId, päivä] of numeroi(päivät)) {
+ const solu = document.createElement('td');
+ solu.id = `lukkari-solu-${päiväId}-${aikaId}`;
+ teePudotuskohteeksi(solu);
+ const lista = document.createElement('ul');
+ solu.appendChild(lista);
+ rivi.appendChild(solu)
+ }
+ rivit.appendChild(rivi);
+ }
+ taulukko.appendChild(rivit);
+
+ const lista = document.createElement('ul');
+ lista.id = 'sijoittamattomat';
+ teePudotuskohteeksi(lista);
+
+ const valinta = document.getElementById('lukkari-valinta').value;
+ if (valinta !== '') {
+ let [tyyppi, valintaId] = valinta.split('-');
+ valintaId = Number.parseInt(valintaId);
+ const tunnit = _tietokanta.järjestyksessä(taulut.tunnit,
+ (a, b) => vertaa(tuntiTeksti(_tietokanta, a), tuntiTeksti(_tietokanta, b))
+ );
+ for (const id of tunnit) {
+ const tunti = _tietokanta.hae(taulut.tunnit, id);
+ if (
+ (tyyppi === 'luokka' && !tunti.luokat.includes(valintaId)) ||
+ (tyyppi === 'opettaja' && !tunti.opettajat.includes(valintaId)) ||
+ (tyyppi === 'tila' && !tunti.tilat.includes(valintaId))
+ ) {
+ continue;
+ }
+ for (const [numero, toteutus] of numeroi(tunti.milloin)) {
+ const laatta = document.createElement('li');
+ laatta.id = `lukkari-tunti-${id}-${numero}`;
+ laatta.draggable = true;
+ laatta.appendChild(document.createTextNode(tuntiTeksti(_tietokanta, tunti)));
+ if (toteutus === null) {
+ lista.appendChild(laatta);
+ } else {
+ const [päiväId, aikaId] = toteutus;
+ const solu = rivit.children[aikaId + 1].children[päiväId + 1];
+ solu.firstChild.appendChild(laatta);
+ }
+ }
+ }
+ }
+
+ const vanhaTaulukko = document.getElementById('lukkari');
+ vanhaTaulukko.parentElement.replaceChild(taulukko, vanhaTaulukko);
+ const vanhaLista = document.getElementById('sijoittamattomat');
+ vanhaLista.parentElement.replaceChild(lista, vanhaLista);
+}
+
+function numeroi(iteroitava) {
+ return iteroitava.map((elementti, numero) => [numero, elementti]);
+}
diff --git a/tietokanta.js b/tietokanta.js
index 8e9096f..318925a 100644
--- a/tietokanta.js
+++ b/tietokanta.js
@@ -234,6 +234,19 @@ class Tietokanta {
return taulukko.map(([id, _]) => id);
}
+ 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)) {
+ if (suodatin(sisältö)) {
+ suodatetut.push(id);
+ }
+ }
+ return suodatetut;
+ }
+
serialisoi() {
return JSON.stringify(this, (avain, arvo) => {
if (avain === 'historia') {
diff --git a/tyyli.css b/tyyli.css
index 46fcac9..41741bd 100644
--- a/tyyli.css
+++ b/tyyli.css
@@ -8,3 +8,15 @@
.valintalista > li {
flex: 1 fit-content;
}
+
+#lukkari {
+ border-collapse: collapse;
+}
+
+#lukkari td {
+ border: 1px solid black;
+}
+
+#lukkari th {
+ border: 1px solid black;
+}