diff options
-rw-r--r-- | app.js | 2 | ||||
-rwxr-xr-x | cli.js | 7 | ||||
-rw-r--r-- | db.js | 6 | ||||
-rw-r--r-- | overview/public/index.html | 13 | ||||
-rw-r--r-- | secrets/index.js | 45 | ||||
-rw-r--r-- | secrets/public/index.html | 44 | ||||
-rw-r--r-- | secrets/public/script.js | 27 | ||||
-rw-r--r-- | secrets/public/style.css | 78 | ||||
-rw-r--r-- | tables.sql | 13 |
9 files changed, 228 insertions, 7 deletions
@@ -13,6 +13,7 @@ const profile = require("./profile"); const admin = require("./admin"); const questions = require("./questions"); const prediction = require("./prediction"); +const secrets = require("./secrets"); const app = express(); @@ -41,6 +42,7 @@ app.use("/poll", checkUser, poll); app.use("/profile", checkUser, profile); app.use("/questions", checkUser, questions); app.use("/prediction", checkUser, prediction); +app.use("/secrets", checkUser, secrets); app.use("/admin", checkAdmin, admin); // Lel app.use("/auth", auth); @@ -40,6 +40,12 @@ if ((idx = params.indexOf("-r")) > -1) { .then(() => process.exit(0)) .catch(console.error); break; + case "secrets": + db.resetSecrets() + .then(() => console.info("Reset secrets!")) + .then(() => process.exit(0)) + .catch(console.error); + break; case "questions": db.resetQuestions() .then(() => console.info("Reset questions!")) @@ -90,7 +96,6 @@ if ((idx = params.indexOf("-r")) > -1) { .then(() => db.initProfiles()) .then(() => console.info("Updating profile!")) .then(() => db.initQuestions()) - .then(() => console.info("Updating Quotes")) .then(() => process.exit(0)) .catch(console.error); @@ -56,6 +56,12 @@ class DB { await this.query(tables[3]); } + async resetSecrets() { + const tables = await this.getTables(); + await this.query("DROP TABLE IF EXISTS secrets"); + await this.query(tables[17]); + } + async resetProfiles() { const tables = await this.getTables(); await this.query("DROP TABLE IF EXISTS profile_comments"); diff --git a/overview/public/index.html b/overview/public/index.html index d63f8ce..2d6cdd5 100644 --- a/overview/public/index.html +++ b/overview/public/index.html @@ -27,7 +27,7 @@ </p> <p> Ihr solltet inzwischen eure Benutzernamen und Passwörter erhalten haben, mit welchen ihr folgende Tools - nutzen könnt: + nutzen könnt/sollt: </p> <div class="pure-menu"> <ul class="pure-menu-list"> @@ -35,9 +35,6 @@ <a href="/mottovote" class="pure-menu-link">Motto-Voting</a> </li>--> <li class="pure-menu-item"> - <a href="/quotes" class="pure-menu-link">Zitate</a> - </li> - <li class="pure-menu-item"> <a href="/profile" class="pure-menu-link">Dein Steckbrief</a> </li> <li class="pure-menu-item"> @@ -50,10 +47,16 @@ <a href="/poll?type=teacher" class="pure-menu-link">Lehrer-Ranking</a> </li> <li class="pure-menu-item"> + <a href="/prediction" class="pure-menu-link">Lehrerauswahl</a> + </li> + <li class="pure-menu-item"> + <a href="/quotes" class="pure-menu-link">Zitate</a> + </li> + <li class="pure-menu-item"> <a href="/questions" class="pure-menu-link">Fragen</a> </li> <li class="pure-menu-item"> - <a href="/prediction" class="pure-menu-link">Lehrerauswahl</a> + <a href="/secrets" class="pure-menu-link">Es ist kein Geheimnis, dass...</a> </li> <li class="pure-menu-item"> <a href="/images" target="_blank" class="pure-menu-link">Klassenbilder</a> diff --git a/secrets/index.js b/secrets/index.js new file mode 100644 index 0000000..22a6f9c --- /dev/null +++ b/secrets/index.js @@ -0,0 +1,45 @@ +const express = require("express"); +const db = require("../db"); +const app = express.Router(); +const { checkUser } = require("../auth"); + +app.use("/", checkUser, express.static(__dirname + "/public")); + +app.post("/api/add", checkUser, async (req, res) => { + if (!req.body.secret) return res.send("error"); + try { + await db.query("INSERT INTO secrets (user_id, secret) VALUE (?,?)", [ + req.session.uid, + req.body.secret.replace(/</g, "<").replace(/>/g, ">"), + ]); + res.redirect("/secrets"); + } catch (e) { + console.error(e); + res.json("error"); + } +}); + +app.get("/api/list", checkUser, async (req, res) => { + const secrets = await db.query( + "SELECT s.id, s.secret, c.name class, (s.user_id = ? OR ?) AS owner FROM secrets s INNER JOIN users u ON u.id = s.user_id INNER JOIN class c ON c.id = u.class_id", + [req.session.uid, req.session.isSuperAdmin || false], + ); + res.json(secrets); +}); + +app.delete("/api/delete/:id", checkUser, async (req, res) => { + if (!req.params.id) return res.send("error"); + try { + await db.query("DELETE FROM secrets WHERE id = ? AND (user_id = ? OR ?)", [ + req.params.id, + req.session.uid, + req.session.isSuperAdmin || false, + ]); + res.send("ok"); + } catch (e) { + console.error(e); + res.send("error"); + } +}); + +module.exports = app; diff --git a/secrets/public/index.html b/secrets/public/index.html new file mode 100644 index 0000000..5aa734d --- /dev/null +++ b/secrets/public/index.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <link + rel="stylesheet" + href="https://unpkg.com/purecss@2.0.3/build/pure-min.css" + integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" + crossorigin="anonymous" + /> + <link rel="stylesheet" href="style.css" type="text/css" media="all" /> + + <title>Zitate</title> + </head> + <body> + <div class="pure-menu pure-menu-horizontal"> + <a href="/" class="pure-menu-item pure-menu-link">Home</a> + <a href="/auth/api/logout" class="pure-menu-item pure-menu-link">Logout</a> + </div> + + <main> + <form class="pure-form pure-form-stacked" action="api/add" method="post"> + <fieldset> + <legend>Es ist kein Geheimnis, dass...</legend> + <input + name="secret" + type="text" + id="secret" + placeholder="Kein Geheimnis" + maxlength="255" + required + /> + <button type="submit" class="pure-button pure-button-primary">Hinzufügen</button> + </fieldset> + </form> + + <p>Es ist kein Geheimnis, dass...</p> + <ul id="list"></ul> + </main> + + <script src="script.js" charset="utf-8"></script> + </body> +</html> diff --git a/secrets/public/script.js b/secrets/public/script.js new file mode 100644 index 0000000..881df3a --- /dev/null +++ b/secrets/public/script.js @@ -0,0 +1,27 @@ +const list = document.getElementById("list"); + +function appendsecret(response) { + response.forEach((elem) => { + list.insertAdjacentHTML( + "beforeend", + `<li><span class="text">${elem["secret"]}</span>${ + elem["owner"] ? ' <span class="delete-btn" data-id="' + elem["id"] + '"></span></li><hr>' : "" + }`, + ); + + const span = document.querySelector(`li span[data-id="${elem["id"]}"]`); + if (span) + span.addEventListener("click", (event) => { + if (!confirm("Bist du dir sicher, dass du das Zitat löschen willst?")) return; + fetch("api/delete/" + event.target.getAttribute("data-id"), { method: "DELETE" }) + .then((response) => response.text()) + .then((response) => { + if (response == "ok") event.target.parentNode.remove(); + }); + }); + }); +} + +fetch("api/list") + .then((response) => response.json()) + .then((response) => appendsecret(response)); diff --git a/secrets/public/style.css b/secrets/public/style.css new file mode 100644 index 0000000..8e759da --- /dev/null +++ b/secrets/public/style.css @@ -0,0 +1,78 @@ +html, +body { + padding: 0; + margin: 0; + height: 100%; + width: 100%; + color: #424242; + line-height: 1.6; + background-color: #eec0c6; + background-image: linear-gradient(315deg, #eec0c6 0%, #7ee8fa 74%); +} + +div { + background: white; +} + +main { + position: absolute; + max-height: calc(100% - 140px); + overflow-y: auto; + width: 50%; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + padding: 20px; + border-radius: 10px; + background: white; +} + +button:not([type="submit"]) { + background-color: #eee; + color: #444; + cursor: pointer; + padding: 18px; + width: 100%; + border: none; + text-align: left; + outline: none; + font-size: 15px; +} + +li { + display: flex; + flex-flow: row wrap; + justify-content: space-between; + vertical-align: top; + margin: 10px 0; +} + +ul { + padding-left: 5px; +} + +span.text { + word-break: break-all; + width: 90%; +} + +span.delete-btn { + cursor: pointer; + background: url("/feather/icons/trash.svg") no-repeat center; + width: 10%; + height: auto; +} + +input, +button, +select { + width: 100%; + color: #424242; +} + +@media only screen and (max-width: 700px) { + main { + width: calc(100% - 20%); + } +} @@ -186,4 +186,15 @@ CREATE TABLE IF NOT EXISTS teacher_prediction CONSTRAINT `fk_teacher_user` FOREIGN KEY (user_id) REFERENCES users (id), CONSTRAINT `fk_teacher_teacher` FOREIGN KEY (teacher_id) REFERENCES users (id) ) ENGINE = InnoDB - DEFAULT CHARSET = utf8;
\ No newline at end of file + DEFAULT CHARSET = utf8; + +CREATE TABLE IF NOT EXISTS secrets +( + id INTEGER PRIMARY KEY AUTO_INCREMENT, + user_id INTEGER NOT NULL, + secret VARCHAR(255) NOT NULL, + + UNIQUE KEY uk_secret (user_id, secret), + CONSTRAINT `fk_user_secret` FOREIGN KEY (user_id) REFERENCES users (id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8; |