let dateOptions = {month: 'short', year: 'numeric'}; let textareaLoaded = false; document.addEventListener('DOMContentLoaded', () => { // check if the user is logged in, if not redirect to log in fetch('/api/user/isLoggedIn').then(res => { if (!res.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(res => { res.json().then(json => { if (res.ok) { for (let i = 0; i < json.length; i++) { addEduData(json[i].ID, json[i].startPeriod, json[i].endPeriod, json[i].grade, json[i].course); } return; } document.querySelector("#edu").innerHTML = "No education data found"; }) }); fetch("/api/timelineData/work").then(res => { res.json().then(json => { if (res.ok) { for (let i = 0; i < json.length; i++) { let endPeriod = json[i].endPeriod === "0000-00-00" ? "Present" : json[i].endPeriod; addWorkData(json[i].ID, json[i].startPeriod, endPeriod, json[i].companyName, json[i].area, json[i].title); } return; } document.querySelector("#edu").innerHTML = "No education data found"; }) }); fetch("/api/projectData").then(res => { res.json().then(json => { if (res.ok) { json.forEach(item => { addProject(item["ID"], (item["isMainProject"] === "1" ? "true" : "false"), (item["imgLocation"] === "") ? "../imgs/placeholder.png" : item["imgLocation"], item["title"], item["information"], item["projectLink"], item["gitLink"]); }) return; } document.querySelector("#projList").innerHTML = "No project data found"; }) }) }) document.querySelector("body").addEventListener("click", () => { if (textareaLoaded) { return; } const tx = document.querySelectorAll("main.editor textarea"); console.log(tx) for (let i = 0; i < tx.length; i++) { console.log("height: " + tx[i].scrollHeight + "px"); tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;"); tx[i].oninput = e => { e.target.style.height = "0"; e.target.style.height = (e.target.scrollHeight) + "px"; }; } textareaLoaded = true; }); 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 data = new FormData(); data.append("dateFrom", document.querySelector("#dateFromE").value); data.append("dateTo", document.querySelector("#dateToE").value); data.append("grade", document.querySelector("#grade").value); data.append("course", document.querySelector("#courseTitle").value); fetch("/api/timelineData/edu", { method: "POST", body: data, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => res.json().then(json => { if (res.ok) { addEduData(json.ID, data.get("dateFrom"), data.get("dateTo"), data.get("grade"), data.get("course"), true); document.querySelector("#addEdu").reset(); return; } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(json.error, "edu"); })); }); document.querySelector("#addWork").addEventListener("submit", e => { e.preventDefault(); let data = new FormData(); data.append("dateFrom", document.querySelector("#dateFromW").value); data.append("dateTo", document.querySelector("#dateToW").value); data.append("companyName", document.querySelector("#company").value); data.append("area", document.querySelector("#area").value); data.append("title", document.querySelector("#jobTitle").value); fetch("/api/timelineData/work", { method: "POST", body: data, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => res.json().then(json => { if (res.ok) { let endPeriod = data.get("dateTo") === "" ? "Present" : data.get("dateTo "); addWorkData(json.ID, data.get("dateFrom"), endPeriod, data.get("companyName"), data.get("area"), data.get("title"), true); document.querySelector("#addWork").reset(); return; } if (res.status === 401) { window.location.href = "./"; return; } showErrorMessage(json.error, "work"); })); }); 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) ? document.querySelector("#projLink").value : "N/A"); 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, data.get("isMainProject"),"../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, data.get("isMainProject"), 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", () => { textareaLoaded = false; 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 = false; 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(res => { if (res.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")); /** * Shows respective error message for form * @param {string} message The error message to show * @param {string} form The form to show the error message for */ function showErrorMessage(message, form) { document.querySelector(`#${form}Error`).classList.remove("hidden"); document.querySelector(`#${form}Error div`).innerText = message; } /** * Switches the timeline item between edit and view mode * @param id the id of the timeline item from the database */ function editCVItem(id) { textareaLoaded = false; document.querySelector(`#timelineItem${id}`).classList.toggle("editing"); if (id.includes("e")) { document.querySelector(`#grade${id}`).toggleAttribute("disabled"); document.querySelector(`#course${id}`).toggleAttribute("disabled"); return; } document.querySelector(`#companyName${id}`).toggleAttribute("disabled"); document.querySelector(`#area${id}`).toggleAttribute("disabled"); document.querySelector(`#jobTitle${id}`).toggleAttribute("disabled"); } /** * Updates the education timeline item with the given id * @param {number} ID - the id of the course timeline item from the database * @param {string} startPeriod - the start date of the course * @param {string} endPeriod - the end date of the course * @param {string} grade - the grade of the course * @param {string} course - the name of the course * @param {boolean} prepend - whether to prepend the timeline item to the timeline */ function addEduData(ID, startPeriod, endPeriod, grade, course, prepend=false) { let id = ID + "e"; let timelineItem = document.createElement("form") timelineItem.id = "timelineItem" + id; timelineItem.classList.add("timelineItem"); timelineItem.onsubmit = e => updateEduItem(ID, e); timelineItem.innerHTML = `
-

${new Date(startPeriod).toLocaleString('en-gb', dateOptions)} - ${new Date(endPeriod).toLocaleString('en-gb', dateOptions)}

`; if (prepend) { document.querySelector("#edu").prepend(timelineItem); return; } document.getElementById("edu").appendChild(timelineItem); } /** * Adds a new work timeline item to the page * @param {number} ID - the id of the work timeline item from the database * @param {string} startPeriod - the start date of the job * @param {string} endPeriod - the end date of the job * @param {string} companyName - the name of the company * @param {string} area - the area of the company * @param {string} jobTitle - the job title * @param {boolean} prepend - whether to prepend the timeline item to the timeline */ function addWorkData(ID, startPeriod, endPeriod, companyName, area, jobTitle, prepend=false) { let id = ID + "w"; let timelineItem = document.createElement("form") timelineItem.id = "timelineItem" + id; timelineItem.classList.add("timelineItem"); timelineItem.onsubmit = e => updateWorkItem(ID, e); timelineItem.innerHTML = `
-

${new Date(startPeriod).toLocaleString('en-gb', dateOptions)} - ${endPeriod === 'Present' ? 'Present' : new Date(endPeriod).toLocaleString('en-gb', dateOptions)}

-
`; if (prepend) { document.querySelector("#work").prepend(timelineItem); return; } document.getElementById("work").appendChild(timelineItem); } /** * Updates the edu timeline item with the given id * and data from the form * @param {number} id the id of the edu timeline item from the database * @param {SubmitEvent} e the event that triggered the function */ function updateEduItem(id, e) { e.preventDefault(); let data = {} data["dateFrom"] = document.querySelector(`#dateFrom${id}e`).value; data["dateTo"] = document.querySelector(`#dateTo${id}e`).value; data["grade"] = document.querySelector(`#grade${id}e`).value; data["course"] = document.querySelector(`#course${id}e`).value; fetch("/api/timelineData/edu/" + id, { method: "PATCH", body: JSON.stringify(data), headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if (res.ok) { document.querySelector(`#timelineHeader${id}e`).innerHTML = new Date(document.querySelector(`#dateFrom${id}e`).value).toLocaleString('en-gb', dateOptions) + " - " + new Date(document.querySelector(`#dateTo${id}e`).value).toLocaleString('en-gb', dateOptions); document.querySelector(`#timelineItem${id}e`).classList.toggle("editing"); document.querySelector(`#grade${id}e`).setAttribute("disabled", ""); document.querySelector(`#course${id}e`).setAttribute("disabled", ""); return; } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => { document.querySelector(`#eduError${id}e`).classList.remove("hidden"); document.querySelector(`#eduError${id}e div`).innerHTML = json.error; }); }) } /** * Updates the work timeline item with the given id * and data from the form * @param {number} id the id of the work timeline item from the database * @param {SubmitEvent} e the event that triggered the function */ function updateWorkItem(id, e) { e.preventDefault(); let data = {} data["dateFrom"] = document.querySelector(`#dateFrom${id}w`).value; data["dateTo"] = document.querySelector(`#dateTo${id}w`).value; data["companyName"] = document.querySelector(`#companyName${id}w`).value; data["area"] = document.querySelector(`#area${id}w`).value; data["title"] = document.querySelector(`#jobTitle${id}w`).value; fetch("/api/timelineData/work/" + id, { method: "PATCH", body: JSON.stringify(data), headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if(res.ok) { document.querySelector(`#timelineHeader${id}w`).innerHTML = new Date(document.querySelector(`#dateFrom${id}w`).value).toLocaleString('en-gb', dateOptions) + " - " + new Date(document.querySelector(`#dateTo${id}w`).value).toLocaleString('en-gb', dateOptions); document.querySelector(`#timelineItem${id}w`).classList.toggle("editing"); document.querySelector(`#companyName${id}w`).setAttribute("disabled", ""); document.querySelector(`#area${id}w`).setAttribute("disabled", ""); document.querySelector(`#jobTitle${id}w`).setAttribute("disabled", ""); return; } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => { document.querySelector(`#workError${id}w`).classList.remove("hidden"); document.querySelector(`#workError${id}w div`).innerHTML = json.error; }); }); } /** * Deletes the timeline item with the given id * @param {number} id the id of the timeline item */ function deleteEduItem(id) { fetch("/api/timelineData/edu/" + id, { method: "DELETE", headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if (res.ok) { document.querySelector(`#timelineItem${id}e`).remove(); return; } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => alert(json.error)); }); } /** * Updates the timeline item with the given id * @param {number} id the id of the timeline item from the database */ function deleteWorkItem(id) { fetch("/api/timelineData/work/" + id, { method: "DELETE", headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if (res.ok) { document.querySelector(`#timelineItem${id}w`).remove(); return; } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => alert(json.error)); }); } /** * Updates the project item with the given id * and data from the form * @param {number} id the id from the database * @param {SubmitEvent} e the event of the form that was submitted */ function updateProjectItem(id, e) { e.preventDefault(); let data = {} data["title"] = document.querySelector(`#title${id}`).value; data["isMainProject"] = document.querySelector(`#isMainProject${id}`).checked ? "true" : "false"; data["information"] = document.querySelector(`#info${id}`).value; data["projectLink"] = document.querySelector(`#viewProj${id}`).value; data["gitLink"] = document.querySelector(`#git${id}`).value; let imgData = new FormData(); imgData.append("img", document.querySelector(`#img${id}`).files[0]); fetch("/api/projectData/" + id, { method: "PATCH", body: JSON.stringify(data), headers: { "Content-Type": "application/json", "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if (res.ok) { if (imgData.get("img") === "undefined") { if (data["isMainProject"] === "true") { document.querySelectorAll(".isMainProject input").forEach(item => item.checked = false); document.querySelector(`#isMainProject${id}`).checked = true; document.querySelector("#projList").prepend(document.querySelector(`#projectItem${id}`)); } document.querySelector(`#projectItem${id}`).classList.toggle("editing"); document.querySelector(`#title${id}`).setAttribute("disabled", ""); document.querySelector(`#info${id}`).setAttribute("disabled", ""); return; } console.log("updating image") return fetch("/api/projectImage/" + id, { method: "POST", body: imgData, headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }); } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(projectDataError => { document.querySelector(`#projError${id}`).classList.remove("hidden"); document.querySelector(`#projError${id} div`).innerHTML = projectDataError.error; }); }).then(res => res.json().then(updatedProjectImage => { if (res.ok) { if (updatedProjectImage["isMainProject"] === "true") { document.querySelectorAll(".isMainProject input").forEach(item => item.checked = false); document.querySelector(`#isMainProject${id}`).checked = true; document.querySelector("#projList").prepend(document.querySelector(`#projectItem${id}`)); } document.querySelector(`#projectItem${id}`).classList.toggle("editing"); document.querySelector(`#title${id}`).setAttribute("disabled", ""); document.querySelector(`#info${id}`).setAttribute("disabled", ""); document.querySelector(`#projectImage${id}`).src = updatedProjectImage.imgLocation; return; } if (res.status === 401) { window.location.href = "./"; return; } document.querySelector(`#projError${id}`).classList.remove("hidden"); document.querySelector(`#projError${id} div`).innerHTML = updatedProjectImage.error; })); } /** * Toggles the editing mode of the project item with the given id * @param id {number} the id of the project item from the database */ function editProjectItem(id) { document.querySelector(`#projectItem${id}`).classList.toggle("editing"); document.querySelector(`#title${id}`).removeAttribute("disabled"); document.querySelector(`#info${id}`).removeAttribute("disabled"); } /** * Deletes the project item with the given id * @param id {number} the id of the project item from the database */ function deleteProjectItem(id) { fetch("/api/projectData/" + id, { method: "DELETE", headers: { "Authorization": "Bearer " + localStorage.getItem("token") } }).then(res => { if (res.ok) { document.querySelector(`#projectItem${id}`).remove(); return; } if (res.status === 401) { window.location.href = "./"; return; } res.json().then(json => alert(json.error)); }); } /** * Adds a new project to the page * @param {number} id the id of the project from the database * @param {string} isMainProject is it the main project * @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 , isMainProject, imgLocation, title, information, projectLink, gitLink) { let projectItem = document.createElement("form"); projectItem.id = "projectItem" + id; projectItem.classList.add("projItem"); projectItem.onsubmit = e => updateProjectItem(id, e); projectItem.innerHTML = `
image preivew of the project
`; if (isMainProject === "true") { document.querySelectorAll(".isMainProject input").forEach(item => item.checked = false); document.querySelector("#projList").prepend(projectItem); return; } document.querySelector("#projList").appendChild(projectItem); }