diff --git a/dist/api/index.php b/dist/api/index.php
index 895708d..8219ffa 100644
--- a/dist/api/index.php
+++ b/dist/api/index.php
@@ -1,6 +1,5 @@
get("/projectData", function (Request $request, Response $response)
$app->patch("/projectData/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
- if (empty($args["id"] != "undefined"))
+ $data = $request->getParsedBody();
+ if ($args["id"] != "undefined")
{
- if (empty($args["title"]) || empty($args["isMainProject"]) || empty($args["information"]) || empty($args["projectLink"]) || empty($args["githubLink"]))
+ if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["projectLink"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
- if (!$projectData->updateProjectData($args["title"], $args["isMainProject"], $args["information"], $args["projectLink"], $args["githubLink"], $args["id"]))
+ if (!$projectData->updateProjectData($args["id"], $data["title"], $data["isMainProject"], $data["information"], "", $data["projectLink"], $data["gitLink"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
@@ -261,14 +261,14 @@ $app->post("/projectData", function (Request $request, Response $response)
{
global $projectData;
$data = $request->getParsedBody();
- if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["projectLink"]) || empty($data["githubLink"]))
+ if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["projectLink"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
- $insertedID = $projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["githubLink"]);
+ $insertedID = $projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
@@ -280,6 +280,29 @@ $app->post("/projectData", function (Request $request, Response $response)
return $response;
});
+$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
+{
+ global $projectData;
+ $files = $request->getUploadedFiles();
+ if (empty($args["id"]) || empty($files))
+ {
+ // uh oh only some of the data was sent
+ $response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
+ return $response->withStatus(400);
+ }
+
+ $message = $projectData->uploadImage($args["id"], $files["img"]);
+ if (!is_array($message))
+ {
+ // uh oh something went wrong
+ $response->getBody()->write(json_encode(array("error" => $message)));
+ return $response->withStatus(500);
+ }
+
+ $response->getBody()->write(json_encode($message));
+ return $response;
+});
+
$app->post("/contact", function (Request $request, Response $response)
{
$data = $request->getParsedBody();
@@ -479,6 +502,12 @@ $app->post("/user/login", function (Request $request, Response $response)
return $response->withStatus(401);
});
+$app->get("/user/logout", function (Request $request, Response $response)
+{
+ session_unset();
+ return $response;
+});
+
$app->get("/user/isLoggedIn", function (Request $request, Response $response)
{
global $user;
@@ -498,7 +527,7 @@ $app->get("/user/isLoggedIn", function (Request $request, Response $response)
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
-
+
});
$app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
diff --git a/dist/api/middleware.php b/dist/api/middleware.php
index 2b9bc0d..be8f9b5 100644
--- a/dist/api/middleware.php
+++ b/dist/api/middleware.php
@@ -2,11 +2,14 @@
// middleware
namespace api;
+session_start();
+
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\App;
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
+use Slim\Exception\HttpInternalServerErrorException;
use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException;
use Slim\Psr7\Response;
@@ -76,7 +79,7 @@ class middleware
$app->add(new JwtAuthentication([
"rules" => [
new RequestPathRule([
- "path" => ["/api/projectData", "/api/timeline/[a-z]*", "/api/user/testMethod"],
+ "path" => ["/api/projectData", "/api/timeline/[a-z]*", "/api/logout"],
"ignore" => ["/api/contact", "/api/user/login", "/api/user/changePassword"]
]),
new RequestMethodRule([
@@ -114,6 +117,12 @@ class middleware
$response->getBody()->write(json_encode(array("status" => "405", "message" => "Method not allowed")));
return $response;
}
+ catch (HttpInternalServerErrorException $exception)
+ {
+ $response = (new Response())->withStatus(500);
+ $response->getBody()->write(json_encode(array("status" => "500", "message" => $exception->getMessage())));
+ return $response;
+ }
});
$app->addErrorMiddleware(true, true, true);
diff --git a/dist/api/projectData.php b/dist/api/projectData.php
index 285ad9c..d72e614 100644
--- a/dist/api/projectData.php
+++ b/dist/api/projectData.php
@@ -1,6 +1,7 @@
prepare("SELECT title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects order by date LIMIT 4;");
+ $stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects;");
$stmt->execute();
// set the resulting array to associative
@@ -27,57 +28,141 @@ class projectData
{
return $result;
}
+
return array("errorMessage" => "Error, project data not found");
}
- function updateProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $githubLink, string $id): bool
+
+ /**
+ * Update project data in the database with the given ID
+ * @param string $ID - ID of the project in the database to update
+ * @param string $title - Title of the project
+ * @param bool $isMainProject - Is the project a main project or not
+ * @param string $information - Information about the project
+ * @param string $imgLocation - Location of the image
+ * @param string $projectLink - Link to the project
+ * @param string $gitLink - Link to the github repository
+ * @return bool - True if project was updated, false if not and there was an error
+ */
+ function updateProjectData(string $ID, string $title, bool $isMainProject, string $information, string $imgLocation, string $projectLink, string $gitLink): bool
{
$conn = dbConn();
- $stmt = $conn->prepare("UPDATE projects SET title = :title, isMainProject = :isMainProject, information = :information, projectLink = :projectLink, githubLink = :githubLink WHERE ID = :id");
+ $stmt = $conn->prepare("UPDATE projects SET title = :title, isMainProject = :isMainProject, information = :information, imgLocation = :imgLocation, projectLink = :projectLink, gitLink = :gitLink WHERE ID = :ID");
+ $stmt->bindParam(":title", $title);
+ $stmt->bindParam(":isMainProject", $isMainProject);
+ $stmt->bindParam(":information", $information);
+ $stmt->bindParam(":imgLocation", $imgLocation);
+ $stmt->bindParam(":projectLink", $projectLink);
+ $stmt->bindParam(":gitLink", $gitLink);
+ $stmt->bindParam(":ID", $ID);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Delete project data from the database
+ * @param int $ID - ID of the project in the database to delete
+ * @return bool - True if project was deleted, false if not and there was an error
+ */
+ function deleteProjectData(int $ID): bool
+ {
+ $conn = dbConn();
+ $stmt = $conn->prepare("DELETE FROM projects WHERE ID = :ID");
+ $stmt->bindParam(":ID", $ID);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Add project data to the database
+ * @param string $title - Title of the project
+ * @param string $isMainProject - Is the project a main project or not
+ * @param string $information - Information about the project
+ * @param string $projectLink - Link to the project
+ * @param string $gitLink - Link to the github repository
+ * @return int|bool - ID of the project if it was added, false if not and there was an error
+ */
+ function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool
+ {
+ $conn = dbConn();
+ $stmt = $conn->prepare("INSERT INTO projects (title, isMainProject, information, projectLink, gitLink) VALUES (:title, :isMainProject, :information, :projectLink, :gitLink)");
$stmt->bindParam(":title", $title);
$stmt->bindParam(":isMainProject", $isMainProject);
$stmt->bindParam(":information", $information);
$stmt->bindParam(":projectLink", $projectLink);
- $stmt->bindParam(":githubLink", $githubLink);
- $stmt->bindParam(":id", $id);
+ $stmt->bindParam(":gitLink", $gitLink);
$stmt->execute();
if ($stmt->rowCount() > 0)
{
- return true;
+ return $conn->lastInsertId();
}
+
return false;
}
- function deleteProjectData(int $id): bool
+ /**
+ * Upload the image to the server and update the database with the new image location
+ * @param int $ID - ID of the project in the database to update
+ * @param UploadedFileInterface $img - Image preview of the project
+ * @return string|array - String with error message or array with the new image location
+ */
+ public function uploadImage(int $ID, UploadedFileInterface $img): string | array
{
- $conn = dbConn();
- $stmt = $conn->prepare("DELETE FROM projects WHERE ID = :id");
- $stmt->bindParam(":id", $id);
- $stmt->execute();
+ $targetDir = "../imgs/projects/";
+ $targetFile = $targetDir . basename($img->getClientFilename());
+ $uploadOk = 1;
+ $imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
- if ($stmt->rowCount() > 0)
+ // Check if file already exists
+ if (file_exists($targetFile))
{
- return true;
+ return "The file already exists";
}
- return false;
- }
- function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $githubLink): bool
- {
- $conn = dbConn();
- $stmt = $conn->prepare("INSERT INTO projects (title, isMainProject, information, projectLink, githubLink) VALUES (:title, :isMainProject, :information, :projectLink, :githubLink)");
- $stmt->bindParam(":title", $title);
- $stmt->bindParam(":isMainProject", $isMainProject);
- $stmt->bindParam(":information", $information);
- $stmt->bindParam(":projectLink", $projectLink);
- $stmt->bindParam(":githubLink", $githubLink);
- $stmt->execute();
-
- if ($stmt->rowCount() > 0)
+ // Check file size
+ if ($img->getSize() > 2000000)
{
- return true;
+ return "The file is too large, max 2MB";
}
- return false;
+
+ // Allow certain file formats
+ if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif")
+ {
+ return "Only JPG, JPEG, PNG & GIF files are allowed";
+ }
+
+ $img->moveTo($targetFile);
+
+ if (file_exists($targetFile))
+ {
+ // update the database with the new image location
+ $conn = dbConn();
+ $stmt = $conn->prepare("UPDATE projects SET imgLocation = :imgLocation WHERE ID = :ID");
+ $stmt->bindParam(":imgLocation", $targetFile);
+ $stmt->bindParam(":ID", $ID);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ {
+ return array("imgLocation" => $targetFile);
+ }
+
+ return "Couldn't update the database";
+ }
+
+ return "Couldn't upload the image";
}
}
diff --git a/dist/editor/editor.html b/dist/editor/editor.html
index 61eb7e1..5b468f7 100644
--- a/dist/editor/editor.html
+++ b/dist/editor/editor.html
@@ -1 +1 @@
-
Editor☰
Editor
\ No newline at end of file
+Editor☰
Editor
\ No newline at end of file
diff --git a/dist/editor/js/editor.js b/dist/editor/js/editor.js
index 9f0a78e..2526df3 100644
--- a/dist/editor/js/editor.js
+++ b/dist/editor/js/editor.js
@@ -1 +1 @@
-let dateOptions={month:"short",year:"numeric"},textareaLoaded=!1;function showErrorMessage(e,t){document.querySelector(`#${t}Error`).classList.remove("hidden"),document.querySelector(`#${t}Error div`).innerText=e}function editCVItem(e){if(textareaLoaded=!1,document.querySelector(`#timelineItem${e}`).classList.toggle("editing"),e.includes("e"))return document.querySelector(`#grade${e}`).toggleAttribute("disabled"),void document.querySelector(`#course${e}`).toggleAttribute("disabled");document.querySelector(`#companyName${e}`).toggleAttribute("disabled"),document.querySelector(`#area${e}`).toggleAttribute("disabled"),document.querySelector(`#jobTitle${e}`).toggleAttribute("disabled")}function addEduData(e,t,o,n,r,a=!1){let i=e+"e",d=document.createElement("form");d.id="timelineItem"+i,d.classList.add("timelineItem"),d.onsubmit=t=>updateEduItem(e,t),d.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n \n \n
\n \n \n
\n \n \n \n `,a?document.querySelector("#edu").prepend(d):document.getElementById("edu").appendChild(d)}function addWorkData(e,t,o,n,r,a,i=!1){let d=e+"w",l=document.createElement("form");l.id="timelineItem"+d,l.classList.add("timelineItem"),l.onsubmit=t=>updateWorkItem(e,t),l.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n \n -\n \n
\n \n \n
\n \n \n \n\t`,i?document.querySelector("#work").prepend(l):document.getElementById("work").appendChild(l)}function updateEduItem(e,t){t.preventDefault();let o={};o.dateFrom=document.querySelector(`#dateFrom${e}e`).value,o.dateTo=document.querySelector(`#dateTo${e}e`).value,o.grade=document.querySelector(`#grade${e}e`).value,o.course=document.querySelector(`#course${e}e`).value,fetch("/api/timelineData/edu/"+e,{method:"PATCH",body:JSON.stringify(o),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}e`).innerHTML=new Date(document.querySelector(`#dateFrom${e}e`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}e`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}e`).classList.toggle("editing"),document.querySelector(`#grade${e}e`).setAttribute("disabled",""),void document.querySelector(`#course${e}e`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#eduError${e}e`).classList.remove("hidden"),document.querySelector(`#eduError${e}e div`).innerHTML=t.error})):window.location.href="./"}))}function updateWorkItem(e,t){t.preventDefault();let o={};o.dateFrom=document.querySelector(`#dateFrom${e}w`).value,o.dateTo=document.querySelector(`#dateTo${e}w`).value,o.companyName=document.querySelector(`#companyName${e}w`).value,o.area=document.querySelector(`#area${e}w`).value,o.title=document.querySelector(`#jobTitle${e}w`).value,fetch("/api/timelineData/work/"+e,{method:"PATCH",body:JSON.stringify(o),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}w`).innerHTML=new Date(document.querySelector(`#dateFrom${e}w`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}w`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}w`).classList.toggle("editing"),document.querySelector(`#companyName${e}w`).setAttribute("disabled",""),document.querySelector(`#area${e}w`).setAttribute("disabled",""),void document.querySelector(`#jobTitle${e}w`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#workError${e}w`).classList.remove("hidden"),document.querySelector(`#workError${e}w div`).innerHTML=t.error})):window.location.href="./"}))}function deleteEduItem(e){fetch("/api/timelineData/edu/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}e`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function deleteWorkItem(e){fetch("/api/timelineData/work/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}w`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function updateProjectItem(e,t){t.preventDefault();let o={};o.title=document.querySelector(`#title${e}`).value,o.isMainProject=document.querySelector(`#isMainProject${e}`).checked,o.img=document.querySelector(`#img${e}`).files[0],o.information=document.querySelector(`#info${e}`).value,o.projectLink=document.querySelector(`#viewProj${e}`).value,o.gitLink=document.querySelector(`#git${e}`).value}function editProjectItem(e){document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).removeAttribute("disabled"),document.querySelector(`#info${e}`).removeAttribute("disabled")}function deleteProjectItem(e){}function addProject(e,t,o,n,r){let a=document.createElement("form");a.id="projectItem"+e,a.classList.add("projItem"),a.onsubmit=t=>updateProjectItem(e,t),a.innerHTML=`\n \n \n \n
\n \n \n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n \n `,document.querySelector("#projList").appendChild(a)}document.addEventListener("DOMContentLoaded",(()=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok||(window.location.href="./")})),document.querySelector("#dateFromE").max=(new Date).toISOString().split("T")[0],document.querySelector("#dateFromW").max=(new Date).toISOString().split("T")[0],fetch("/api/timelineData/edu").then((e=>{e.json().then((t=>{if(e.ok)for(let e=0;e{e.json().then((t=>{if(e.ok)for(let e=0;e{e.json().then((t=>{e.ok?t.forEach((e=>{addProject(e.ID,e.title,e.information,e.projectLink,e.gitLink)})):document.querySelector("#projects").innerHTML="No project data found"}))}))})),document.querySelector("body").addEventListener("click",(()=>{if(textareaLoaded)return;const e=document.querySelectorAll("main.editor textarea");console.log(e);for(let t=0;t{e.target.style.height="0",e.target.style.height=e.target.scrollHeight+"px"};textareaLoaded=!0})),document.querySelector("#navOpen").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.removeProperty("width"),document.querySelector("main.editor").style.removeProperty("margin-left"),e.target.style.removeProperty("visibility")})),document.querySelector("#navClose").addEventListener("click",(()=>{document.querySelector("nav.sideNav").style.width="0",document.querySelector("main.editor").style.marginLeft="0",document.querySelector("#navOpen").style.visibility="visible"})),document.querySelector("#addEdu").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromE").value),t.append("dateTo",document.querySelector("#dateToE").value),t.append("grade",document.querySelector("#grade").value),t.append("course",document.querySelector("#courseTitle").value),fetch("/api/timelineData/edu",{method:"POST",body:t,headers:{Authentication:localStorage.getItem("token")}}).then((e=>e.json().then((o=>{if(e.ok)return addEduData(o.ID,t.get("dateFrom"),t.get("dateTo"),t.get("grade"),t.get("course"),!0),void document.querySelector("#addEdu").reset();401!==e.status?showErrorMessage(o.error,"edu"):window.location.href="./"}))))})),document.querySelector("#addWork").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromW").value),t.append("dateTo",document.querySelector("#dateToW").value),t.append("companyName",document.querySelector("#company").value),t.append("area",document.querySelector("#area").value),t.append("title",document.querySelector("#jobTitle").value),fetch("/api/timelineData/work",{method:"POST",body:t,headers:{Authentication:localStorage.getItem("token")}}).then((e=>e.json().then((o=>{if(e.ok){let e=null===t.get("dateTo")?"Present":t.get("dateTo ");return addWorkData(o.ID,t.get("dateFrom"),e,t.get("companyName"),t.get("area"),t.get("title"),!0),void document.querySelector("#addWork").reset()}401!==e.status?showErrorMessage(o.error,"work"):window.location.href="./"}))))})),document.querySelector("#goToCV").addEventListener("click",(()=>{textareaLoaded=!1,document.querySelector("#curriculumVitae").style.display="block",document.querySelector("#goToCV").classList.add("active"),document.querySelector("#projects").style.display="none",document.querySelector("#goToProjects").classList.remove("active")})),document.querySelector("#goToProjects").addEventListener("click",(()=>{textareaLoaded=!1,document.querySelector("#curriculumVitae").style.display="none",document.querySelector("#goToCV").classList.remove("active"),document.querySelector("#projects").style.display="block",document.querySelector("#goToProjects").classList.add("active")})),document.querySelector("#logout").addEventListener("click",(()=>{fetch("/api/user/logout").then((e=>{e.ok&&(localStorage.removeItem("token"),window.location.reload())}))})),document.querySelector("#eduError .close").addEventListener("click",(()=>document.querySelector("#eduError").classList.toggle("hidden"))),document.querySelector("#workError .close").addEventListener("click",(()=>document.querySelector("#workError").classList.toggle("hidden")));
\ No newline at end of file
+let dateOptions={month:"short",year:"numeric"},textareaLoaded=!1;function showErrorMessage(e,t){document.querySelector(`#${t}Error`).classList.remove("hidden"),document.querySelector(`#${t}Error div`).innerText=e}function editCVItem(e){if(textareaLoaded=!1,document.querySelector(`#timelineItem${e}`).classList.toggle("editing"),e.includes("e"))return document.querySelector(`#grade${e}`).toggleAttribute("disabled"),void document.querySelector(`#course${e}`).toggleAttribute("disabled");document.querySelector(`#companyName${e}`).toggleAttribute("disabled"),document.querySelector(`#area${e}`).toggleAttribute("disabled"),document.querySelector(`#jobTitle${e}`).toggleAttribute("disabled")}function addEduData(e,t,o,r,n,a=!1){let i=e+"e",d=document.createElement("form");d.id="timelineItem"+i,d.classList.add("timelineItem"),d.onsubmit=t=>updateEduItem(e,t),d.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n \n \n
\n \n \n
\n \n \n \n `,a?document.querySelector("#edu").prepend(d):document.getElementById("edu").appendChild(d)}function addWorkData(e,t,o,r,n,a,i=!1){let d=e+"w",l=document.createElement("form");l.id="timelineItem"+d,l.classList.add("timelineItem"),l.onsubmit=t=>updateWorkItem(e,t),l.innerHTML=`\n \n \n \n
\n \n \n -\n \n
\n \n \n \n -\n \n
\n \n \n
\n \n \n \n\t`,i?document.querySelector("#work").prepend(l):document.getElementById("work").appendChild(l)}function updateEduItem(e,t){t.preventDefault();let o={};o.dateFrom=document.querySelector(`#dateFrom${e}e`).value,o.dateTo=document.querySelector(`#dateTo${e}e`).value,o.grade=document.querySelector(`#grade${e}e`).value,o.course=document.querySelector(`#course${e}e`).value,fetch("/api/timelineData/edu/"+e,{method:"PATCH",body:JSON.stringify(o),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}e`).innerHTML=new Date(document.querySelector(`#dateFrom${e}e`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}e`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}e`).classList.toggle("editing"),document.querySelector(`#grade${e}e`).setAttribute("disabled",""),void document.querySelector(`#course${e}e`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#eduError${e}e`).classList.remove("hidden"),document.querySelector(`#eduError${e}e div`).innerHTML=t.error})):window.location.href="./"}))}function updateWorkItem(e,t){t.preventDefault();let o={};o.dateFrom=document.querySelector(`#dateFrom${e}w`).value,o.dateTo=document.querySelector(`#dateTo${e}w`).value,o.companyName=document.querySelector(`#companyName${e}w`).value,o.area=document.querySelector(`#area${e}w`).value,o.title=document.querySelector(`#jobTitle${e}w`).value,fetch("/api/timelineData/work/"+e,{method:"PATCH",body:JSON.stringify(o),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#timelineHeader${e}w`).innerHTML=new Date(document.querySelector(`#dateFrom${e}w`).value).toLocaleString("en-gb",dateOptions)+" - "+new Date(document.querySelector(`#dateTo${e}w`).value).toLocaleString("en-gb",dateOptions),document.querySelector(`#timelineItem${e}w`).classList.toggle("editing"),document.querySelector(`#companyName${e}w`).setAttribute("disabled",""),document.querySelector(`#area${e}w`).setAttribute("disabled",""),void document.querySelector(`#jobTitle${e}w`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#workError${e}w`).classList.remove("hidden"),document.querySelector(`#workError${e}w div`).innerHTML=t.error})):window.location.href="./"}))}function deleteEduItem(e){fetch("/api/timelineData/edu/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}e`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function deleteWorkItem(e){fetch("/api/timelineData/work/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#timelineItem${e}w`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function updateProjectItem(e,t){t.preventDefault();let o={};o.title=document.querySelector(`#title${e}`).value,o.isMainProject=document.querySelector(`#isMainProject${e}`).checked,o.img=document.querySelector(`#img${e}`).files[0],o.information=document.querySelector(`#info${e}`).value,o.projectLink=document.querySelector(`#viewProj${e}`).value,o.gitLink=document.querySelector(`#git${e}`).value,fetch("/api/projectData/"+e,{method:"PATCH",body:JSON.stringify(o),headers:{"Content-Type":"application/json",Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).setAttribute("disabled",""),void document.querySelector(`#info${e}`).setAttribute("disabled","");401!==t.status?t.json().then((t=>{document.querySelector(`#projError${e}`).classList.remove("hidden"),document.querySelector(`#projError${e} div`).innerHTML=t.error})):window.location.href="./"}))}function editProjectItem(e){document.querySelector(`#projectItem${e}`).classList.toggle("editing"),document.querySelector(`#title${e}`).removeAttribute("disabled"),document.querySelector(`#info${e}`).removeAttribute("disabled")}function deleteProjectItem(e){fetch("/api/projectData/"+e,{method:"DELETE",headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{t.ok?document.querySelector(`#projectItem${e}`).remove():401!==t.status?t.json().then((e=>alert(e.error))):window.location.href="./"}))}function addProject(e,t,o,r,n,a){let i=document.createElement("form");i.id="projectItem"+e,i.classList.add("projItem"),i.onsubmit=t=>updateProjectItem(e,t),i.innerHTML=`\n \n \n \n
\n \n \n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n
\n \n \n \n `,document.querySelector("#projList").appendChild(i)}document.addEventListener("DOMContentLoaded",(()=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok||(window.location.href="./")})),document.querySelector("#dateFromE").max=(new Date).toISOString().split("T")[0],document.querySelector("#dateFromW").max=(new Date).toISOString().split("T")[0],fetch("/api/timelineData/edu").then((e=>{e.json().then((t=>{if(e.ok)for(let e=0;e{e.json().then((t=>{if(e.ok)for(let e=0;e{e.json().then((t=>{e.ok?t.forEach((e=>{addProject(e.ID,""===e.imgLocation?"../imgs/placeholder.png":e.imgLocation,e.title,e.information,e.projectLink,e.gitLink)})):document.querySelector("#projects").innerHTML="No project data found"}))}))})),document.querySelector("body").addEventListener("click",(()=>{if(textareaLoaded)return;const e=document.querySelectorAll("main.editor textarea");console.log(e);for(let t=0;t{e.target.style.height="0",e.target.style.height=e.target.scrollHeight+"px"};textareaLoaded=!0})),document.querySelector("#navOpen").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.removeProperty("width"),document.querySelector("main.editor").style.removeProperty("margin-left"),e.target.style.removeProperty("visibility")})),document.querySelector("#navClose").addEventListener("click",(()=>{document.querySelector("nav.sideNav").style.width="0",document.querySelector("main.editor").style.marginLeft="0",document.querySelector("#navOpen").style.visibility="visible"})),document.querySelector("#addEdu").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromE").value),t.append("dateTo",document.querySelector("#dateToE").value),t.append("grade",document.querySelector("#grade").value),t.append("course",document.querySelector("#courseTitle").value),fetch("/api/timelineData/edu",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((o=>{if(e.ok)return addEduData(o.ID,t.get("dateFrom"),t.get("dateTo"),t.get("grade"),t.get("course"),!0),void document.querySelector("#addEdu").reset();401!==e.status?showErrorMessage(o.error,"edu"):window.location.href="./"}))))})),document.querySelector("#addWork").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("dateFrom",document.querySelector("#dateFromW").value),t.append("dateTo",document.querySelector("#dateToW").value),t.append("companyName",document.querySelector("#company").value),t.append("area",document.querySelector("#area").value),t.append("title",document.querySelector("#jobTitle").value),fetch("/api/timelineData/work",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((o=>{if(e.ok){let e=null===t.get("dateTo")?"Present":t.get("dateTo ");return addWorkData(o.ID,t.get("dateFrom"),e,t.get("companyName"),t.get("area"),t.get("title"),!0),void document.querySelector("#addWork").reset()}401!==e.status?showErrorMessage(o.error,"work"):window.location.href="./"}))))})),document.querySelector("#addProj").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;t.append("title",document.querySelector("#projTitle").value),t.append("isMainProject",document.querySelector("#isMainProject").checked?"true":"false"),t.append("information",document.querySelector("#projInfo").value),t.append("projectLink",document.querySelector("#projLink").value),t.append("gitLink",document.querySelector("#gitLink").value);let o=new FormData;o.append("img",document.querySelector("#projImg").files[0]);let r=0;fetch("/api/projectData",{method:"POST",body:t,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((e=>e.json().then((n=>{if(e.ok)return"undefined"===o.get("img")?(addProject(n.ID,"../imgs/placeholder.png",t.get("title"),t.get("information"),t.get("projectLink"),t.get("gitLink")),void document.querySelector("#addProj").reset()):(r=n.ID,fetch("/api/projectImage/"+n.ID,{method:"POST",body:o,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}));401!==e.status?showErrorMessage(n.error,"proj"):window.location.href="./"})).then((e=>e.json().then((o=>{if(e.ok)return addProject(r,o.imgLocation,t.get("title"),t.get("information"),t.get("projectLink"),t.get("gitLink")),void document.querySelector("#addProj").reset();401!==e.status?showErrorMessage(o.error,"proj"):window.location.href="./"}))))))})),document.querySelector("#goToCV").addEventListener("click",(()=>{textareaLoaded=!1,document.querySelector("#curriculumVitae").style.display="block",document.querySelector("#goToCV").classList.add("active"),document.querySelector("#projects").style.display="none",document.querySelector("#goToProjects").classList.remove("active")})),document.querySelector("#goToProjects").addEventListener("click",(()=>{textareaLoaded=!1,document.querySelector("#curriculumVitae").style.display="none",document.querySelector("#goToCV").classList.remove("active"),document.querySelector("#projects").style.display="block",document.querySelector("#goToProjects").classList.add("active")})),document.querySelector("#logout").addEventListener("click",(()=>{fetch("/api/user/logout").then((e=>{e.ok&&window.location.reload()}))})),document.querySelector("#eduError .close").addEventListener("click",(()=>document.querySelector("#eduError").classList.toggle("hidden"))),document.querySelector("#workError .close").addEventListener("click",(()=>document.querySelector("#workError").classList.toggle("hidden"))),document.querySelector("#projError .close").addEventListener("click",(()=>document.querySelector("#projError").classList.toggle("hidden")));
\ No newline at end of file
diff --git a/src/api/index.php b/src/api/index.php
index 895708d..8219ffa 100644
--- a/src/api/index.php
+++ b/src/api/index.php
@@ -1,6 +1,5 @@
get("/projectData", function (Request $request, Response $response)
$app->patch("/projectData/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
- if (empty($args["id"] != "undefined"))
+ $data = $request->getParsedBody();
+ if ($args["id"] != "undefined")
{
- if (empty($args["title"]) || empty($args["isMainProject"]) || empty($args["information"]) || empty($args["projectLink"]) || empty($args["githubLink"]))
+ if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["projectLink"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
- if (!$projectData->updateProjectData($args["title"], $args["isMainProject"], $args["information"], $args["projectLink"], $args["githubLink"], $args["id"]))
+ if (!$projectData->updateProjectData($args["id"], $data["title"], $data["isMainProject"], $data["information"], "", $data["projectLink"], $data["gitLink"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
@@ -261,14 +261,14 @@ $app->post("/projectData", function (Request $request, Response $response)
{
global $projectData;
$data = $request->getParsedBody();
- if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["projectLink"]) || empty($data["githubLink"]))
+ if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["projectLink"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
- $insertedID = $projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["githubLink"]);
+ $insertedID = $projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
@@ -280,6 +280,29 @@ $app->post("/projectData", function (Request $request, Response $response)
return $response;
});
+$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
+{
+ global $projectData;
+ $files = $request->getUploadedFiles();
+ if (empty($args["id"]) || empty($files))
+ {
+ // uh oh only some of the data was sent
+ $response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
+ return $response->withStatus(400);
+ }
+
+ $message = $projectData->uploadImage($args["id"], $files["img"]);
+ if (!is_array($message))
+ {
+ // uh oh something went wrong
+ $response->getBody()->write(json_encode(array("error" => $message)));
+ return $response->withStatus(500);
+ }
+
+ $response->getBody()->write(json_encode($message));
+ return $response;
+});
+
$app->post("/contact", function (Request $request, Response $response)
{
$data = $request->getParsedBody();
@@ -479,6 +502,12 @@ $app->post("/user/login", function (Request $request, Response $response)
return $response->withStatus(401);
});
+$app->get("/user/logout", function (Request $request, Response $response)
+{
+ session_unset();
+ return $response;
+});
+
$app->get("/user/isLoggedIn", function (Request $request, Response $response)
{
global $user;
@@ -498,7 +527,7 @@ $app->get("/user/isLoggedIn", function (Request $request, Response $response)
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
-
+
});
$app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
diff --git a/src/api/middleware.php b/src/api/middleware.php
index 2b9bc0d..be8f9b5 100644
--- a/src/api/middleware.php
+++ b/src/api/middleware.php
@@ -2,11 +2,14 @@
// middleware
namespace api;
+session_start();
+
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\App;
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
+use Slim\Exception\HttpInternalServerErrorException;
use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException;
use Slim\Psr7\Response;
@@ -76,7 +79,7 @@ class middleware
$app->add(new JwtAuthentication([
"rules" => [
new RequestPathRule([
- "path" => ["/api/projectData", "/api/timeline/[a-z]*", "/api/user/testMethod"],
+ "path" => ["/api/projectData", "/api/timeline/[a-z]*", "/api/logout"],
"ignore" => ["/api/contact", "/api/user/login", "/api/user/changePassword"]
]),
new RequestMethodRule([
@@ -114,6 +117,12 @@ class middleware
$response->getBody()->write(json_encode(array("status" => "405", "message" => "Method not allowed")));
return $response;
}
+ catch (HttpInternalServerErrorException $exception)
+ {
+ $response = (new Response())->withStatus(500);
+ $response->getBody()->write(json_encode(array("status" => "500", "message" => $exception->getMessage())));
+ return $response;
+ }
});
$app->addErrorMiddleware(true, true, true);
diff --git a/src/api/projectData.php b/src/api/projectData.php
index 285ad9c..d72e614 100644
--- a/src/api/projectData.php
+++ b/src/api/projectData.php
@@ -1,6 +1,7 @@
prepare("SELECT title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects order by date LIMIT 4;");
+ $stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects;");
$stmt->execute();
// set the resulting array to associative
@@ -27,57 +28,141 @@ class projectData
{
return $result;
}
+
return array("errorMessage" => "Error, project data not found");
}
- function updateProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $githubLink, string $id): bool
+
+ /**
+ * Update project data in the database with the given ID
+ * @param string $ID - ID of the project in the database to update
+ * @param string $title - Title of the project
+ * @param bool $isMainProject - Is the project a main project or not
+ * @param string $information - Information about the project
+ * @param string $imgLocation - Location of the image
+ * @param string $projectLink - Link to the project
+ * @param string $gitLink - Link to the github repository
+ * @return bool - True if project was updated, false if not and there was an error
+ */
+ function updateProjectData(string $ID, string $title, bool $isMainProject, string $information, string $imgLocation, string $projectLink, string $gitLink): bool
{
$conn = dbConn();
- $stmt = $conn->prepare("UPDATE projects SET title = :title, isMainProject = :isMainProject, information = :information, projectLink = :projectLink, githubLink = :githubLink WHERE ID = :id");
+ $stmt = $conn->prepare("UPDATE projects SET title = :title, isMainProject = :isMainProject, information = :information, imgLocation = :imgLocation, projectLink = :projectLink, gitLink = :gitLink WHERE ID = :ID");
+ $stmt->bindParam(":title", $title);
+ $stmt->bindParam(":isMainProject", $isMainProject);
+ $stmt->bindParam(":information", $information);
+ $stmt->bindParam(":imgLocation", $imgLocation);
+ $stmt->bindParam(":projectLink", $projectLink);
+ $stmt->bindParam(":gitLink", $gitLink);
+ $stmt->bindParam(":ID", $ID);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Delete project data from the database
+ * @param int $ID - ID of the project in the database to delete
+ * @return bool - True if project was deleted, false if not and there was an error
+ */
+ function deleteProjectData(int $ID): bool
+ {
+ $conn = dbConn();
+ $stmt = $conn->prepare("DELETE FROM projects WHERE ID = :ID");
+ $stmt->bindParam(":ID", $ID);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Add project data to the database
+ * @param string $title - Title of the project
+ * @param string $isMainProject - Is the project a main project or not
+ * @param string $information - Information about the project
+ * @param string $projectLink - Link to the project
+ * @param string $gitLink - Link to the github repository
+ * @return int|bool - ID of the project if it was added, false if not and there was an error
+ */
+ function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool
+ {
+ $conn = dbConn();
+ $stmt = $conn->prepare("INSERT INTO projects (title, isMainProject, information, projectLink, gitLink) VALUES (:title, :isMainProject, :information, :projectLink, :gitLink)");
$stmt->bindParam(":title", $title);
$stmt->bindParam(":isMainProject", $isMainProject);
$stmt->bindParam(":information", $information);
$stmt->bindParam(":projectLink", $projectLink);
- $stmt->bindParam(":githubLink", $githubLink);
- $stmt->bindParam(":id", $id);
+ $stmt->bindParam(":gitLink", $gitLink);
$stmt->execute();
if ($stmt->rowCount() > 0)
{
- return true;
+ return $conn->lastInsertId();
}
+
return false;
}
- function deleteProjectData(int $id): bool
+ /**
+ * Upload the image to the server and update the database with the new image location
+ * @param int $ID - ID of the project in the database to update
+ * @param UploadedFileInterface $img - Image preview of the project
+ * @return string|array - String with error message or array with the new image location
+ */
+ public function uploadImage(int $ID, UploadedFileInterface $img): string | array
{
- $conn = dbConn();
- $stmt = $conn->prepare("DELETE FROM projects WHERE ID = :id");
- $stmt->bindParam(":id", $id);
- $stmt->execute();
+ $targetDir = "../imgs/projects/";
+ $targetFile = $targetDir . basename($img->getClientFilename());
+ $uploadOk = 1;
+ $imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
- if ($stmt->rowCount() > 0)
+ // Check if file already exists
+ if (file_exists($targetFile))
{
- return true;
+ return "The file already exists";
}
- return false;
- }
- function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $githubLink): bool
- {
- $conn = dbConn();
- $stmt = $conn->prepare("INSERT INTO projects (title, isMainProject, information, projectLink, githubLink) VALUES (:title, :isMainProject, :information, :projectLink, :githubLink)");
- $stmt->bindParam(":title", $title);
- $stmt->bindParam(":isMainProject", $isMainProject);
- $stmt->bindParam(":information", $information);
- $stmt->bindParam(":projectLink", $projectLink);
- $stmt->bindParam(":githubLink", $githubLink);
- $stmt->execute();
-
- if ($stmt->rowCount() > 0)
+ // Check file size
+ if ($img->getSize() > 2000000)
{
- return true;
+ return "The file is too large, max 2MB";
}
- return false;
+
+ // Allow certain file formats
+ if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif")
+ {
+ return "Only JPG, JPEG, PNG & GIF files are allowed";
+ }
+
+ $img->moveTo($targetFile);
+
+ if (file_exists($targetFile))
+ {
+ // update the database with the new image location
+ $conn = dbConn();
+ $stmt = $conn->prepare("UPDATE projects SET imgLocation = :imgLocation WHERE ID = :ID");
+ $stmt->bindParam(":imgLocation", $targetFile);
+ $stmt->bindParam(":ID", $ID);
+ $stmt->execute();
+
+ if ($stmt->rowCount() > 0)
+ {
+ return array("imgLocation" => $targetFile);
+ }
+
+ return "Couldn't update the database";
+ }
+
+ return "Couldn't upload the image";
}
}
diff --git a/src/editor/editor.html b/src/editor/editor.html
index 478ec97..693901a 100644
--- a/src/editor/editor.html
+++ b/src/editor/editor.html
@@ -121,26 +121,30 @@
-
-
+
+
-
-
+
+
-
-
+
+
+
diff --git a/src/editor/js/editor.js b/src/editor/js/editor.js
index bf85aa6..5568841 100644
--- a/src/editor/js/editor.js
+++ b/src/editor/js/editor.js
@@ -56,7 +56,7 @@ document.addEventListener('DOMContentLoaded', () =>
{
json.forEach(item =>
{
- addProject(item["ID"], item["title"], item["information"], item["projectLink"], item["gitLink"]);
+ addProject(item["ID"], (item["imgLocation"] === "") ? "../imgs/placeholder.png" : item["imgLocation"], item["title"], item["information"], item["projectLink"], item["gitLink"]);
})
return;
}
@@ -114,7 +114,7 @@ document.querySelector("#addEdu").addEventListener("submit", e =>
method: "POST",
body: data,
headers: {
- "Authentication": localStorage.getItem("token")
+ "Authorization": "Bearer " + localStorage.getItem("token")
}
}).then(res => res.json().then(json =>
{
@@ -149,7 +149,7 @@ document.querySelector("#addWork").addEventListener("submit", e =>
method: "POST",
body: data,
headers: {
- "Authentication": localStorage.getItem("token")
+ "Authorization": "Bearer " + localStorage.getItem("token")
}
}).then(res => res.json().then(json =>
{
@@ -170,6 +170,75 @@ document.querySelector("#addWork").addEventListener("submit", e =>
}));
});
+document.querySelector("#addProj").addEventListener("submit", e =>
+{
+ e.preventDefault();
+ let data = new FormData();
+ data.append("title", document.querySelector("#projTitle").value);
+ data.append("isMainProject", document.querySelector("#isMainProject").checked ? "true" : "false");
+ data.append("information", document.querySelector("#projInfo").value);
+ data.append("projectLink", document.querySelector("#projLink").value);
+ data.append("gitLink", document.querySelector("#gitLink").value);
+
+ let imgData = new FormData();
+ imgData.append("img", document.querySelector("#projImg").files[0]);
+
+ let newProjectID = 0;
+
+ fetch("/api/projectData", {
+ method: "POST",
+ body: data,
+ headers: {
+ "Authorization": "Bearer " + localStorage.getItem("token")
+ }
+ }).then(res => res.json().then(newProjectData =>
+ {
+ if (res.ok)
+ {
+ if (imgData.get("img") === "undefined")
+ {
+ addProject(newProjectData.ID, "../imgs/placeholder.png", data.get("title"), data.get("information"), data.get("projectLink"), data.get("gitLink"));
+ document.querySelector("#addProj").reset();
+ return;
+ }
+
+ newProjectID = newProjectData.ID;
+
+ return fetch("/api/projectImage/" + newProjectData.ID, {
+ method: "POST",
+ body: imgData,
+ headers: {
+ "Authorization": "Bearer " + localStorage.getItem("token")
+ }
+ });
+ }
+
+ if (res.status === 401)
+ {
+ window.location.href = "./";
+ return;
+ }
+
+ showErrorMessage(newProjectData.error, "proj");
+ }).then(res => res.json().then(newProjectImage =>
+ {
+ if (res.ok)
+ {
+ addProject(newProjectID, newProjectImage.imgLocation, data.get("title"), data.get("information"), data.get("projectLink"), data.get("gitLink"));
+ document.querySelector("#addProj").reset();
+ return;
+ }
+
+ if (res.status === 401)
+ {
+ window.location.href = "./";
+ return;
+ }
+
+ showErrorMessage(newProjectImage.error, "proj");
+
+ })));
+});
document.querySelector("#goToCV").addEventListener("click", () =>
{
@@ -195,7 +264,6 @@ document.querySelector("#logout").addEventListener("click", () =>
{
if (res.ok)
{
- localStorage.removeItem("token");
window.location.reload();
}
});
@@ -207,6 +275,9 @@ document.querySelector("#eduError .close").addEventListener("click", () =>
document.querySelector("#workError .close").addEventListener("click", () =>
document.querySelector("#workError").classList.toggle("hidden"));
+document.querySelector("#projError .close").addEventListener("click", () =>
+ document.querySelector("#projError").classList.toggle("hidden"));
+
/**
* Shows respective error message for form
* @param {string} message The error message to show
@@ -534,8 +605,8 @@ function updateProjectItem(id, e)
res.json().then(json =>
{
- document.querySelector(`#projectError${id}`).classList.remove("hidden");
- document.querySelector(`#projectError${id} div`).innerHTML = json.error;
+ document.querySelector(`#projError${id}`).classList.remove("hidden");
+ document.querySelector(`#projError${id} div`).innerHTML = json.error;
});
});
@@ -584,12 +655,13 @@ function deleteProjectItem(id)
/**
* Adds a new project to the page
* @param {number} id the id of the project from the database
+ * @param {string} imgLocation the relative path of the image
* @param {string} title the title of the project
* @param {string} information the information about the project
* @param {string} projectLink the link to the project
* @param {string} gitLink the link to the git repository
*/
-function addProject(id, title, information, projectLink, gitLink)
+function addProject(id, imgLocation, title, information, projectLink, gitLink)
{
let projectItem = document.createElement("form");
projectItem.id = "projectItem" + id;
@@ -600,7 +672,7 @@ function addProject(id, title, information, projectLink, gitLink)
-
+