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

curriculum vitae

Education

Work

projects

\ No newline at end of file +Editor

Editor

curriculum vitae

Education

Work

projects

\ 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

${new Date(t).toLocaleString("en-gb",dateOptions)} - ${new Date(o).toLocaleString("en-gb",dateOptions)}

\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

${new Date(t).toLocaleString("en-gb",dateOptions)} - ${"Present"===o?"":new Date(o).toLocaleString("en-gb",dateOptions)}

\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 image preivew of the project\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

${new Date(t).toLocaleString("en-gb",dateOptions)} - ${new Date(o).toLocaleString("en-gb",dateOptions)}

\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

${new Date(t).toLocaleString("en-gb",dateOptions)} - ${"Present"===o?"":new Date(o).toLocaleString("en-gb",dateOptions)}

\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 image preivew of the project\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)
- image preivew of the project + image preivew of the project