aboutsummaryrefslogtreecommitdiff
path: root/profile
diff options
context:
space:
mode:
Diffstat (limited to 'profile')
-rw-r--r--profile/index.js92
-rw-r--r--profile/public/index.html8
-rw-r--r--profile/public/script.js76
-rw-r--r--profile/public/style.css2
4 files changed, 97 insertions, 81 deletions
diff --git a/profile/index.js b/profile/index.js
index d9ee068..be0c232 100644
--- a/profile/index.js
+++ b/profile/index.js
@@ -38,87 +38,57 @@ app.get("/api/questions", async (req, res) => {
res.json(questions);
});
-app.post("/api/add", async (req, res) => {
- try {
- for (let qid in req.body) {
- if (!req.body.hasOwnProperty(qid) || req.body[qid] === "dbg-image") continue;
- let answer = req.body[qid].replace(/</g, "&lt;").replace(/>/g, "&gt;");
- try {
- await db.query("INSERT INTO profile_answers (question_id, user_id, answer) VALUES (?, ?, ?)", [
- qid,
- req.session.uid,
- answer.replace(/</g, "&lt;").replace(/>/g, "&gt;"),
- ]);
- } catch (e) {
- console.error(e);
- }
- }
- for (let fid in req.files) {
- if (!req.files.hasOwnProperty(fid)) return;
-
- let image, imageType, imageName;
+app.post("/api/answer", async (req, res) => {
+ return await answer(req, res, "INSERT INTO profile_answers (answer, question_id, user_id) VALUE (?,?,?)");
+});
+app.put("/api/answer", async (req, res) => {
+ return await answer(req, res, "UPDATE profile_answers SET answer = ? WHERE question_id = ? AND user_id = ?");
+});
- image = req.files[fid];
- imageType = image.name.split(".").reverse()[0];
- imageName = `${req.session.uid}_${new Date().getTime()}.${imageType}`;
- image.mv(__dirname + "/public/uploads/" + imageName);
+async function answer(req, res, qs) {
+ try {
+ for (const qid of req.body) {
+ if (!req.body.hasOwnProperty(qid)/* || !req.body[qid]*/) continue;
+ const answer = req.body[qid];
try {
- await db.query("INSERT INTO profile_answers (question_id, user_id, answer) VALUES (?, ?, ?)", [
- fid,
- req.session.uid,
- imageName,
- ]);
+ await db.query(qs, [answer, qid, req.session.uid]); // TODO: Frontend display sanitize
} catch (e) {
console.error(e);
}
}
- res.send("ok");
+ res.json({ success: true });
} catch (e) {
console.error(e);
- res.send("error");
+ res.json({ success: false });
}
+}
+
+app.post("/api/answerImage", async (req, res) => {
+ return await answerImage(req, res, "INSERT INTO profile_answers (answer, question_id, user_id) VALUE (?,?,?)");
+});
+app.put("/api/answerImage", async (req, res) => {
+ return await answerImage(req, res, "UPDATE profile_answers SET answer = ? WHERE question_id = ? AND user_id = ?");
});
-app.put("/api/update", async (req, res) => {
+async function answerImage(req, res, qs) {
try {
- for (let qid in req.body) {
- if (!req.body.hasOwnProperty(qid) || req.body[qid] === "dbg-image") continue;
- let answer = req.body[qid].replace(/</g, "&lt;").replace(/>/g, "&gt;");
- try {
- await db.query("UPDATE profile_answers SET answer = ? WHERE question_id = ? AND user_id = ?", [
- answer,
- qid,
- req.session.uid,
- ]);
- } catch (e) {
- console.error(e);
- }
- }
- for (let fid in req.files) {
- if (!req.files.hasOwnProperty(fid)) return;
-
- let image, imageType, imageName;
-
- image = req.files[fid];
- imageType = image.name.split(".").reverse()[0];
- imageName = `${req.session.uid}_${new Date().getTime()}.${imageType}`;
- image.mv(__dirname + "/public/uploads/" + imageName);
+ for (const fid in req.files) {
+ if (!req.files.hasOwnProperty(fid)) continue;
+ const image = req.files[fid];
+ const name = `${req.session.uid}_${new Date().getTime()}.jpg`;
try {
- await db.query("UPDATE profile_answers SET answer = ? WHERE question_id = ? AND user_id = ?", [
- imageName,
- fid,
- req.session.uid,
- ]);
+ await image.mv(`${__dirname}/public/uploads/${name}`);
+ await db.query(qs, [name, fid, req.session.uid]);
} catch (e) {
console.error(e);
}
}
- res.send("ok");
+ res.json({ success: true });
} catch (e) {
console.error(e);
- res.send("error");
+ res.json({ success: false });
}
-});
+}
// Comments API
app.get("/api/comments/:uid", async (req, res) => {
diff --git a/profile/public/index.html b/profile/public/index.html
index e6f2e6c..a87fb77 100644
--- a/profile/public/index.html
+++ b/profile/public/index.html
@@ -34,6 +34,14 @@
</main>
<div class="popup">
<img id="popup-img" src="https://fengyuanchen.github.io/cropperjs/images/picture.jpg" alt="Picture" />
+ <button class="pure-button pure-button-primary" id="save-btn">Übernehmen</button>
+ <label for="rotation-slider">Drehen</label>
+ <input id="rotation-slider" type="range" min="-180" max="180" value="0">
+ <div class="control-btns">
+ <button class="pure-button pure-button-primary" id="rot45" data-value="-45" data-rot="true">45</button>
+ <button class="pure-button pure-button-primary" id="nrot45" data-value="45" data-rot="true">-45</button>
+ <button class="pure-button pure-button-primary" id="norm" data-value="0" data-rot="false">0</button>
+ </div>
</div>
<script
diff --git a/profile/public/script.js b/profile/public/script.js
index 1cfb6d3..eb5ff14 100644
--- a/profile/public/script.js
+++ b/profile/public/script.js
@@ -1,15 +1,20 @@
const fs = document.querySelector("fieldset");
const form = document.querySelector("form");
let init = true;
+let imageInit = true;
+let imageID = -1;
const popup = document.querySelector(".popup");
const popupImage = document.querySelector("#popup-img");
+const saveBtn = document.querySelector("#save-btn");
+const slider = document.querySelector("#rotation-slider");
+const controlButtons = document.querySelectorAll(".control-btns button");
+let cropper = undefined;
+
const crop = () => {
- var minAspectRatio = 0.5;
- var maxAspectRatio = 1.5;
- const cropper = new Cropper(document.getElementById("popup-img"), {
+ cropper = new Cropper(document.getElementById("popup-img"), { // Consider dataset id
dragMode: "move",
- aspectRatio: 2 / 3,
+ aspectRatio: 10 / 13,
autoCropArea: 0.65,
restore: false,
guides: false,
@@ -19,7 +24,12 @@ const crop = () => {
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
});
- return cropper;
+};
+
+NodeList.prototype.on = function (listener, event) {
+ for (const node of this) {
+ node.addEventListener(listener, event);
+ }
};
function updateHeading(user) {
@@ -41,6 +51,7 @@ function appendQuestions(question) {
img.src = "uploads/" + question.answer;
img.alt = "Image";
div.appendChild(img);
+ imageInit = false;
}
const field = document.createElement("input");
@@ -51,18 +62,17 @@ function appendQuestions(question) {
field.placeholder = question.question;
field.type = question.type;
if (question.type === "file") {
+ imageID = question.id;
field.accept = "image/*";
field.addEventListener("input", (e) => {
const file = e.target.files[0];
popupImage.file = file;
const reader = new FileReader();
- reader.onload = (function (aImg) {
- return function (e) {
- aImg.src = e.target.result;
- popup.style.display = "block";
- crop();
- };
- })(popupImage);
+ reader.addEventListener("load", (e) => {
+ popupImage.src = e.target.result;
+ popup.style.display = "block";
+ crop();
+ });
reader.readAsDataURL(file);
});
}
@@ -73,20 +83,46 @@ function appendQuestions(question) {
form.addEventListener("submit", async (evt) => {
evt.preventDefault();
- const url = init ? "api/add" : "api/update";
const method = init ? "POST" : "PUT";
const inputs = form.querySelectorAll("input");
- const body = new FormData();
+ const rawBody = {}
for (const input of inputs) {
- if (input.type !== "file") body.append(input.name, input.value);
- else body.append(input.name, input.files[0] ?? "dbg-image");
+ if (input.type !== "file") rawBody[input.name] = input.value;
}
+ const body = JSON.stringify(rawBody);
+
+ const resp = await fetch("api/answer", { method, body });
+ const res = await resp.json();
+ if (!res.success) alert("AHHHH");
+ else init = false;
+ // else location.reload(); // BUT WHY?
+});
+
+saveBtn.addEventListener("click", (e) => {
+ cropper.getCroppedCanvas()
+ .toBlob(async (blob) => {
+ const url = "api/answerImage";
+ const method = imageInit ? "POST" : "PUT"; // Separate image init
+ const body = new FormData();
+ if (imageID === -1) {
+ return;
+ }
+ body.append(imageID, blob);
+ const resp = await fetch(url, { method, body });
+ const res = await resp.json();
+ if (!res.success) alert("AHHH");
+ else imageInit = false;
+ }, "image/jpeg");
+});
+
+slider.addEventListener("input", (e) => {
+ cropper.rotateTo(-e.target.value);
+});
- const resp = await fetch(url, { method, body });
- const res = await resp.text();
- if (res !== "ok") alert("AHHHH");
- else location.reload();
+controlButtons.on("click", (e) => {
+ if (e.target.dataset.rot === "true") cropper.rotate(+e.target.dataset.value);
+ else cropper.rotateTo(+e.target.dataset.value);
});
fetch("/auth/api/self")
diff --git a/profile/public/style.css b/profile/public/style.css
index a30e7ef..66c0bdf 100644
--- a/profile/public/style.css
+++ b/profile/public/style.css
@@ -137,4 +137,6 @@ img {
z-index: 10;
position: absolute;
display: none;
+ max-height: 600px;
+ max-width: 600px;
} \ No newline at end of file