editor-projects #29

Merged
rodude123 merged 7 commits from editor-projects into master 2023-02-07 03:35:44 +00:00
15 changed files with 326 additions and 120 deletions
Showing only changes of commit db7c12857e - Show all commits

2
dist/css/main.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Editor</title><link rel="stylesheet" href="css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script></head><body><nav class="sideNav"><a href="#" class="closeBtn" id="navClose">&times;</a><ul><li><a href="#" id="goToCV" class="active"><span>&lt;</span>CV<span>&gt;</span></a></li><li><a href="#" id="goToProjects"><span>&lt;</span>Projects<span>&gt;</span></a></li><li><a href="#" id="goToSettings"><span>&lt;</span>Settings<span>&gt;</span></a></li><li><a href="#" id="logout"><span>&lt;</span>Logout<span>&gt;</span></a></li></ul></nav><main class="editor" style="margin-left: 250px;"><div class="title"><span id="navOpen">&#9776;</span><h1>Editor</h1></div><section id="curriculumVitae"><h2>curriculum vitae</h2><div class="cvGrid"><div><h3>Education</h3><div class="editorContainer"><form action="" method="POST" id="addEdu"><div class="formControl"><label for="dateFromE">Date From</label> <input type="date" id="dateFromE" name="dateFromE"></div><div class="formControl"><label for="dateToE">Date To</label> <input type="date" id="dateToE" name="dateToE"></div><div class="formControl"><label for="grade">Grade</label> <input type="text" id="grade" name="grade"></div><div class="formControl"><label for="courseTitle">Course Title</label> <input type="text" id="courseTitle" name="courseTitle"></div><div class="error hidden" id="eduError"><button class="close" type="button">&times;</button><div></div></div><input type="submit" class="btn btnPrimary boxShadowIn boxShadowOut" value="Add new course"></form><div class="timeline" id="edu"></div></div></div><div><h3>Work</h3><div class="editorContainer"><form action="" method="POST" id="addWork"><div class="formControl"><label for="dateFromW">Date From</label> <input type="date" id="dateFromW" name="dateFromW"></div><div class="formControl"><label for="dateToW">Date To</label> <input type="date" id="dateToW" name="dateToW"></div><div class="formControl"><label for="company">Company</label> <input type="text" id="company" name="company"></div><div class="formControl"><label for="area">Area</label> <input type="text" id="area" name="area"></div><div class="formControl"><label for="jobTitle">Job Title</label> <input type="text" id="jobTitle" name="jobTitle"></div><div class="error hidden" id="workError"><button class="close" type="button">&times;</button><div></div></div><input type="submit" class="btn btnPrimary boxShadowIn boxShadowOut" value="Add new job"></form><div class="timeline" id="work"></div></div></div></div></section><section id="projects"><h2>projects</h2><div class="projectsGrid"><form action="" id="addProj"><div class="formControl"><label for="projTitle">Title</label> <input type="text" name="projTitle" id="projTitle" required></div><div class="formControl"><label class="checkContainer" for="isMainProject">Is It The Main Project <input type="checkbox" id="isMainProject" name="isMainProject" required> <span class="checkmark"></span></label></div><div class="formControl"><label for="imgLoc">Image</label> <input type="file" name="imgLoc" id="imgLoc"></div><div class="formControl"><label for="projectLink">Project Link</label> <input type="text" name="projectLink" id="projectLink" pattern="https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)"></div><div class="formControl"><label for="gitLink">Git Link</label> <input type="text" name="gitLink" id="gitLink" pattern="https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)" required></div><input type="submit" value="Add new Project" class="btn btnPrimary boxShadowIn boxShadowOut"></form><div id="projList"></div></div></section></main><script src="js/editor.js"></script></body></html> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Editor</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="stylesheet" href="css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script></head><body><nav class="sideNav"><a href="#" class="closeBtn" id="navClose">&times;</a><ul><li><a href="#" id="goToCV"><span>&lt;</span>CV<span>&gt;</span></a></li><li><a href="#" id="goToProjects" class="active"><span>&lt;</span>Projects<span>&gt;</span></a></li><li><a href="#" id="goToSettings"><span>&lt;</span>Settings<span>&gt;</span></a></li><li><a href="#" id="logout"><span>&lt;</span>Logout<span>&gt;</span></a></li></ul></nav><main class="editor" style="margin-left: 250px;"><div class="title"><span id="navOpen">&#9776;</span><h1>Editor</h1></div><section id="curriculumVitae"><h2>curriculum vitae</h2><div class="cvGrid"><div><h3>Education</h3><div class="editorContainer"><form action="" method="POST" id="addEdu"><div class="formControl"><label for="dateFromE">Date From</label> <input type="date" id="dateFromE" name="dateFromE" required></div><div class="formControl"><label for="dateToE">Date To</label> <input type="date" id="dateToE" name="dateToE" required></div><div class="formControl"><label for="grade">Grade</label> <input type="text" id="grade" name="grade" required></div><div class="formControl"><label for="courseTitle">Course Title</label> <input type="text" id="courseTitle" name="courseTitle" required></div><div class="error hidden" id="eduError"><button class="close" type="button">&times;</button><div></div></div><input type="submit" class="btn btnPrimary boxShadowIn boxShadowOut" value="Add new course"></form><div class="timeline" id="edu"></div></div></div><div><h3>Work</h3><div class="editorContainer"><form action="" method="POST" id="addWork"><div class="formControl"><label for="dateFromW">Date From</label> <input type="date" id="dateFromW" name="dateFromW" required></div><div class="formControl"><label for="dateToW">Date To</label> <input type="date" id="dateToW" name="dateToW"></div><div class="formControl"><label for="company">Company</label> <input type="text" id="company" name="company" required></div><div class="formControl"><label for="area">Area</label> <input type="text" id="area" name="area" required></div><div class="formControl"><label for="jobTitle">Job Title</label> <input type="text" id="jobTitle" name="jobTitle" required></div><div class="error hidden" id="workError"><button class="close" type="button">&times;</button><div></div></div><input type="submit" class="btn btnPrimary boxShadowIn boxShadowOut" value="Add new job"></form><div class="timeline" id="work"></div></div></div></div></section><section id="projects"><h2>projects</h2><div class="projectsGrid"><form action="" id="addProj"><div class="formControl"><label for="projTitle">Title</label> <input type="text" name="projTitle" id="projTitle" required></div><div class="formControl"><label class="checkContainer" for="isMainProject">Is It The Main Project <input type="checkbox" id="isMainProject" name="isMainProject" required> <span class="checkmark"></span></label></div><div class="formControl"><label for="img">Image</label> <input type="file" name="img" id="img"></div><div class="formControl"><label for="projectInfo">Description</label> <textarea name="projectInfo" id="projectInfo"></textarea></div><div class="formControl"><label for="projectLink">Project Link</label> <input type="text" name="projectLink" id="projectLink" pattern="https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)"></div><div class="formControl"><label for="gitLink">Git Link</label> <input type="text" name="gitLink" id="gitLink" pattern="https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)" required></div><input type="submit" value="Add new Project" class="btn btnPrimary boxShadowIn boxShadowOut"></form><div id="projList"></div></div></section></main><script src="js/editor.js"></script></body></html>

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Editor</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="stylesheet" href="css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script></head><body><main class="login"><div id="login" class="container shown"><h1>Login To Editor</h1><form action="" method="POST"><div class="formControl"><label for="username">Username</label> <input type="text" id="username" name="username" required></div><div class="formControl"><label for="password">Password</label> <input type="password" id="password" name="password" required> <i class="fa-solid fa-eye"></i></div><div class="error hidden" id="loginError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" id="resetPwd">Reset Password</a></div></form></div><div id="resetPassword" class="container" style="display: none; transform: translateX(150vw)"><h1>Reset Password</h1><form action="#" method="POST"><div class="formControl"><label for="email">Email</label> <input type="email" id="email" name="email"></div><div class="error hidden" id="resetError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" class="loginBtn btn btnPrimary boxShadowIn boxShadowOut" id="loginBtn">Login</a></div></form></div><div id="checkResetCode" class="container" style="display: none; transform: translateX(150vw)"><h1>Check Reset Code</h1><form action="#" method="POST"><div class="formControl"><label for="code">Code</label> <input type="text" id="code" name="code"></div><div class="error hidden" id="resetCodeError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" class="loginBtn btn btnPrimary boxShadowIn boxShadowOut" id="resendEmail">Resend Email</a></div></form></div><div id="changePassword" class="container" style="display: none; transform: translateX(150vw)"><h1>Reset Password</h1><form action="" method="POST"><div class="formControl"><label for="pass">Password</label> <input type="password" name="pass" id="pass"> <i class="fa-solid fa-eye"></i></div><div class="formControl"><label for="rePass">Password</label> <input type="password" name="rePass" id="rePass"> <i class="fa-solid fa-eye"></i></div><div class="error hidden" id="changeError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" class="loginBtn btn btnPrimary boxShadowIn boxShadowOut">Login</a></div></form></div></main><script src="js/index.js"></script></body></html> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Editor</title><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="stylesheet" href="css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script></head><body><main class="login"><div id="login" class="container shown"><h1>Login To Editor</h1><form action="" method="POST"><div class="formControl"><label for="username">Username</label> <input type="text" id="username" name="username" required></div><div class="formControl passwordControl"><label for="password">Password</label> <input type="password" id="password" name="password" required> <i class="fa-solid fa-eye"></i></div><div class="error hidden" id="loginError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" id="resetPwd">Reset Password</a></div></form></div><div id="resetPassword" class="container" style="display: none; transform: translateX(150vw)"><h1>Reset Password</h1><form action="#" method="POST"><div class="formControl"><label for="email">Email</label> <input type="email" id="email" name="email"></div><div class="error hidden" id="resetError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" class="loginBtn btn btnPrimary boxShadowIn boxShadowOut" id="loginBtn">Login</a></div></form></div><div id="checkResetCode" class="container" style="display: none; transform: translateX(150vw)"><h1>Check Reset Code</h1><form action="#" method="POST"><div class="formControl"><label for="code">Code</label> <input type="text" id="code" name="code"></div><div class="error hidden" id="resetCodeError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" class="loginBtn btn btnPrimary boxShadowIn boxShadowOut" id="resendEmail">Resend Email</a></div></form></div><div id="changePassword" class="container" style="display: none; transform: translateX(150vw)"><h1>Reset Password</h1><form action="" method="POST"><div class="formControl"><label for="pass">Password</label> <input type="password" name="pass" id="pass"> <i class="fa-solid fa-eye"></i></div><div class="formControl"><label for="rePass">Password</label> <input type="password" name="rePass" id="rePass"> <i class="fa-solid fa-eye"></i></div><div class="error hidden" id="changeError"><button class="close" type="button">&times;</button><div></div></div><div class="btnContainer"><input type="submit" value="Submit" class="btn btnPrimary boxShadowIn boxShadowOut"> <a href="#" class="loginBtn btn btnPrimary boxShadowIn boxShadowOut">Login</a></div></form></div></main><script src="js/index.js"></script></body></html>

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
function showErrorMessage(e){document.querySelector("#loginError").classList.remove("hidden"),document.querySelector("#loginError div").innerText=e}document.addEventListener("DOMContentLoaded",(e=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok&&(window.location.href="./editor.html")}))})),document.querySelector("#login form").addEventListener("submit",(e=>{e.preventDefault();let r=new FormData;if(e.target.username.value.length>0&&e.target.password.value.length>0)return r.append("username",e.target.username.value),r.append("password",e.target.password.value),void fetch("/api/user/login",{method:"POST",body:r}).then((e=>{e.ok?window.location.href="./editor.html":400!==e.status?(document.querySelector("#loginError").classList.remove("hidden"),document.querySelector("#loginError div").innerHTML="Invalid username or password"):showErrorMessage("Please type in a username and password.")}));document.querySelector("#loginError").classList.remove("hidden"),document.querySelector("#loginError div").innerHTML="Please type in a username and password"})),document.querySelector("#loginError .close").addEventListener("click",(()=>document.querySelector("#loginError").classList.toggle("hidden")));

2
dist/js/main.js vendored

File diff suppressed because one or more lines are too long

View File

@ -69,7 +69,7 @@ section#projects .otherProj > div .oProjItem {
-webkit-border-radius: 10px; -webkit-border-radius: 10px;
-moz-border-radius: 10px; -moz-border-radius: 10px;
border-radius: 10px; border-radius: 10px;
padding: 0 1em; padding: 0.75em 1em;
} }
section#projects .otherProj > div .oProjItem:nth-child(2) { section#projects .otherProj > div .oProjItem:nth-child(2) {

View File

@ -121,25 +121,6 @@ a.btn:active, form input[type="submit"]:active {
text-shadow: 0 6px 4px var(--mutedBlack); text-shadow: 0 6px 4px var(--mutedBlack);
} }
form .formControl {
width: 100%;
}
form .formControl input:not([type="submit"]), form .formControl textarea {
width: 100%;
border: 4px solid var(--primaryDefault);
background: none;
outline: none;
-webkit-border-radius: 1em;
-moz-border-radius: 1em;
border-radius: 0.5em;
padding: 0 0.5em;
}
form .formControl textarea {
padding: 0.5em;
}
form .formControl input:not([type="submit"]).invalid:invalid, form .formControl textarea.invalid:invalid { form .formControl input:not([type="submit"]).invalid:invalid, form .formControl textarea.invalid:invalid {
border: 4px solid var(--errorDefault); border: 4px solid var(--errorDefault);
} }
@ -165,6 +146,10 @@ form .formControl {
align-items: flex-start; align-items: flex-start;
} }
form .formControl.passwordControl {
display: block;
}
form input[type="submit"] { form input[type="submit"] {
align-self: flex-start; align-self: flex-start;
} }
@ -277,10 +262,12 @@ form .formControl .checkContainer .checkmark:after {
form .formControl input[type="file"] { form .formControl input[type="file"] {
padding: 0; padding: 0;
cursor: pointer;
} }
form .formControl input[type="file"]::file-selector-button { form .formControl input[type="file"]::file-selector-button {
background-color: var(--primaryDefault); background-color: var(--primaryDefault);
color: #FFFFFF;
border: 0; border: 0;
border-right: 5px solid var(--mutedBlack); border-right: 5px solid var(--mutedBlack);
padding: 15px; padding: 15px;
@ -290,7 +277,6 @@ form .formControl input[type="file"]::file-selector-button {
-ms-transition: all .5s; -ms-transition: all .5s;
-o-transition: all .5s; -o-transition: all .5s;
transition: all .5s; transition: all .5s;
cursor: pointer;
} }
form .formControl input[type="file"]:hover::file-selector-button { form .formControl input[type="file"]:hover::file-selector-button {

View File

@ -1,5 +1,9 @@
/*** Main editor styles ***/ /*** Main editor styles ***/
textarea {
resize: none;
}
section#curriculumVitae, section#projects, section#settings { section#curriculumVitae, section#projects, section#settings {
margin: 0 2em; margin: 0 2em;
} }
@ -36,11 +40,11 @@ div.editorContainer > *, div.projectsGrid > * {
width: 45%; width: 45%;
} }
section#curriculumVitae { section#projects {
display: block; display: block;
} }
section#projects, section#settings { section#curriculumVitae, section#settings {
display: none; display: none;
} }
@ -50,6 +54,7 @@ div.modifyBtnContainer {
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 0.5em; margin-bottom: 0.5em;
width: 100%;
} }
div.dateContainer, div.companyAreaContainer { div.dateContainer, div.companyAreaContainer {
@ -70,14 +75,17 @@ section#curriculumVitae .timeline {
height: 100%; height: 100%;
} }
section#curriculumVitae .timelineItem { section#curriculumVitae .timelineItem, section#projects .projItem {
color: #FFFFFF;
border: 2px solid var(--timelineItemBrdr);
-webkit-border-radius: 10px; -webkit-border-radius: 10px;
-moz-border-radius: 10px; -moz-border-radius: 10px;
border-radius: 10px; border-radius: 10px;
padding: 0 1rem; padding: 1rem;
position: relative; position: relative;
}
section#curriculumVitae .timelineItem {
border: 2px solid var(--timelineItemBrdr);
color: #FFFFFF;
background-color: var(--primaryHover); background-color: var(--primaryHover);
} }
@ -85,6 +93,9 @@ section#curriculumVitae .timelineItem.editing {
color: #000000; color: #000000;
border: 5px solid var(--primaryDefault); border: 5px solid var(--primaryDefault);
padding: 0.5em; padding: 0.5em;
}
section#curriculumVitae .timelineItem.editing {
background-color: #FFFFFF; background-color: #FFFFFF;
} }
@ -117,12 +128,15 @@ section#curriculumVitae form.timelineItem.editing div.gradeContainer.formControl
section#curriculumVitae form.timelineItem:not(.editing) div.gradeContainer.formControl input, section#curriculumVitae form.timelineItem:not(.editing) div.gradeContainer.formControl input,
section#curriculumVitae form.timelineItem:not(.editing) div.companyAreaContainer.formControl input, section#curriculumVitae form.timelineItem:not(.editing) div.companyAreaContainer.formControl input,
section#curriculumVitae form.timelineItem:not(.editing) .formControl .courseText, section#curriculumVitae form.timelineItem:not(.editing) .formControl .courseText,
section#curriculumVitae form.timelineItem:not(.editing) .formControl .jobTitleText { section#curriculumVitae form.timelineItem:not(.editing) .formControl .jobTitleText,
section#projects form.projItem:not(.editing) div.formControl.projectTitleContainer input,
section#projects form.projItem:not(.editing) div.formControl.infoContainer textarea {
outline: none; outline: none;
border: none; border: none;
-webkit-border-radius: 0; -webkit-border-radius: 0;
-moz-border-radius: 0; -moz-border-radius: 0;
border-radius: 0; border-radius: 0;
resize: none;
} }
section#curriculumVitae form.timelineItem:not(.editing) div.gradeContainer.formControl > *, section#curriculumVitae form.timelineItem:not(.editing) div.gradeContainer.formControl > *,
@ -166,10 +180,6 @@ section#projects #projList .projItem {
border: 1px solid var(--grey); border: 1px solid var(--grey);
gap: 1em; gap: 1em;
box-shadow: 0 6px 4px 0 var(--mutedBlack); box-shadow: 0 6px 4px 0 var(--mutedBlack);
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
padding: 1em;
} }
section#projects #projList { section#projects #projList {
@ -186,7 +196,7 @@ section#projects #projList .projItem img {
padding: 0 1em; padding: 0 1em;
} }
section#projects .projItem .flexCol div:nth-child(2) { section#projects .projItem .linkContainer {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
@ -194,10 +204,32 @@ section#projects .projItem .flexCol div:nth-child(2) {
margin-left: 2em; margin-left: 2em;
} }
section#projects .flexCol div:nth-child(2) .btn { section#projects .linkContainer .btn {
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
} }
#isMainProject { section#projects #isMainProject {
width: auto; width: auto;
} }
section#projects form.projItem:not(.editing) div.formControl.imageContainer,
section#projects form.projItem:not(.editing) div.formControl.isMainProject,
section#projects form.projItem:not(.editing) div.formControl.viewProjContainer,
section#projects form.projItem:not(.editing) div.formControl.gitContainer,
section#projects form.projItem:not(.editing) input[type="submit"],
section#projects form.projItem.editing img.displayedImage,
section#projects form.projItem.editing div.linkContainer {
display: none;
}
section#projects form.projItem:not(.editing) div.formControl.projectTitleContainer input {
font-size: 1.17em;
/*margin: 1em 0;*/
font-weight: bold;
}
section#projects form.projItem:not(.editing) div.formControl.projectTitleContainer input,
section#projects form.projItem:not(.editing) div.formControl.infoContainer textarea{
color: #000000;
}

View File

@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Editor</title> <title>Editor</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/main.css"> <link rel="stylesheet" href="css/main.css">
<script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script> <script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script>
</head> </head>
@ -10,8 +11,8 @@
<nav class="sideNav"> <nav class="sideNav">
<a href="#" class="closeBtn" id="navClose">&times;</a> <a href="#" class="closeBtn" id="navClose">&times;</a>
<ul> <ul>
<li><a href="#" id="goToCV" class="active"><span>&lt;</span>CV<span>&gt;</span></a></li> <li><a href="#" id="goToCV"><span>&lt;</span>CV<span>&gt;</span></a></li>
<li><a href="#" id="goToProjects"><span>&lt;</span>Projects<span>&gt;</span></a></li> <li><a href="#" id="goToProjects" class="active"><span>&lt;</span>Projects<span>&gt;</span></a></li>
<li><a href="#" id="goToSettings"><span>&lt;</span>Settings<span>&gt;</span></a></li> <li><a href="#" id="goToSettings"><span>&lt;</span>Settings<span>&gt;</span></a></li>
<li><a href="#" id="logout"><span>&lt;</span>Logout<span>&gt;</span></a></li> <li><a href="#" id="logout"><span>&lt;</span>Logout<span>&gt;</span></a></li>
</ul> </ul>
@ -33,22 +34,22 @@
<form action="" method="POST" id="addEdu"> <form action="" method="POST" id="addEdu">
<div class="formControl"> <div class="formControl">
<label for="dateFromE">Date From</label> <label for="dateFromE">Date From</label>
<input type="date" id="dateFromE" name="dateFromE"> <input type="date" id="dateFromE" name="dateFromE" required>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="dateToE">Date To</label> <label for="dateToE">Date To</label>
<input type="date" id="dateToE" name="dateToE"> <input type="date" id="dateToE" name="dateToE" required>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="grade">Grade</label> <label for="grade">Grade</label>
<input type="text" id="grade" name="grade"> <input type="text" id="grade" name="grade" required>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="courseTitle">Course Title</label> <label for="courseTitle">Course Title</label>
<input type="text" id="courseTitle" name="courseTitle"> <input type="text" id="courseTitle" name="courseTitle" required>
</div> </div>
<div class="error hidden" id="eduError"> <div class="error hidden" id="eduError">
@ -71,7 +72,7 @@
<form action="" method="POST" id="addWork"> <form action="" method="POST" id="addWork">
<div class="formControl"> <div class="formControl">
<label for="dateFromW">Date From</label> <label for="dateFromW">Date From</label>
<input type="date" id="dateFromW" name="dateFromW"> <input type="date" id="dateFromW" name="dateFromW" required>
</div> </div>
<div class="formControl"> <div class="formControl">
@ -81,17 +82,17 @@
<div class="formControl"> <div class="formControl">
<label for="company">Company</label> <label for="company">Company</label>
<input type="text" id="company" name="company"> <input type="text" id="company" name="company" required>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="area">Area</label> <label for="area">Area</label>
<input type="text" id="area" name="area"> <input type="text" id="area" name="area" required>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="jobTitle">Job Title</label> <label for="jobTitle">Job Title</label>
<input type="text" id="jobTitle" name="jobTitle"> <input type="text" id="jobTitle" name="jobTitle" required>
</div> </div>
<div class="error hidden" id="workError"> <div class="error hidden" id="workError">
@ -125,8 +126,12 @@
</label> </label>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="imgLoc">Image</label> <label for="img">Image</label>
<input type="file" name="imgLoc" id="imgLoc"> <input type="file" name="img" id="img">
</div>
<div class="formControl">
<label for="projectInfo">Description</label>
<textarea name="projectInfo" id="projectInfo"></textarea>
</div> </div>
<div class="formControl"> <div class="formControl">
<label for="projectLink">Project Link</label> <label for="projectLink">Project Link</label>

View File

@ -18,7 +18,7 @@
<input type="text" id="username" name="username" required> <input type="text" id="username" name="username" required>
</div> </div>
<div class="formControl"> <div class="formControl passwordControl">
<label for="password">Password</label> <label for="password">Password</label>
<input type="password" id="password" name="password" required> <input type="password" id="password" name="password" required>
<i class="fa-solid fa-eye"></i> <i class="fa-solid fa-eye"></i>

View File

@ -1,15 +1,16 @@
let dateOptions = {month: 'short', year: 'numeric'}; let dateOptions = {month: 'short', year: 'numeric'};
let textareaLoaded = false;
document.addEventListener('DOMContentLoaded', () => document.addEventListener('DOMContentLoaded', () =>
{ {
// check if the user is logged in, if not redirect to log in // check if the user is logged in, if not redirect to log in
fetch('/api/user/isLoggedIn').then(res => fetch('/api/user/isLoggedIn').then(res =>
{
if (!res.ok)
{ {
if (!res.ok) window.location.href = './';
{ }
window.location.href = './'; });
}
});
document.querySelector("#dateFromE").max = new Date().toISOString().split("T")[0]; document.querySelector("#dateFromE").max = new Date().toISOString().split("T")[0];
document.querySelector("#dateFromW").max = new Date().toISOString().split("T")[0]; document.querySelector("#dateFromW").max = new Date().toISOString().split("T")[0];
@ -55,7 +56,7 @@ document.addEventListener('DOMContentLoaded', () =>
{ {
json.forEach(item => json.forEach(item =>
{ {
addProject(item["information"], item["projectLink"], item["gitLink"]); addProject(item["ID"], item["title"], item["information"], item["projectLink"], item["gitLink"]);
}) })
return; return;
} }
@ -64,6 +65,28 @@ document.addEventListener('DOMContentLoaded', () =>
}) })
}) })
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("#navOpen").addEventListener("click", e =>
{ {
document.querySelector("nav.sideNav").style.removeProperty("width"); document.querySelector("nav.sideNav").style.removeProperty("width");
@ -108,8 +131,7 @@ document.querySelector("#addEdu").addEventListener("submit", e =>
return; return;
} }
document.querySelector("#eduError").classList.remove("hidden"); showErrorMessage(json.error, "edu");
document.querySelector("#eduError div").innerHTML = json.error;
})); }));
}); });
@ -135,7 +157,7 @@ document.querySelector("#addWork").addEventListener("submit", e =>
{ {
let endPeriod = data.get("dateTo") === null ? "Present" : data.get("dateTo "); let endPeriod = data.get("dateTo") === null ? "Present" : data.get("dateTo ");
addWorkData(json.ID, data.get("dateFrom"), endPeriod, data.get("companyName"), data.get("area"), data.get("title"), true); addWorkData(json.ID, data.get("dateFrom"), endPeriod, data.get("companyName"), data.get("area"), data.get("title"), true);
document.querySelector("#addEdu").reset(); document.querySelector("#addWork").reset();
return; return;
} }
@ -144,61 +166,85 @@ document.querySelector("#addWork").addEventListener("submit", e =>
window.location.href = "./"; window.location.href = "./";
return; return;
} }
showErrorMessage(json.error, "work");
document.querySelector("#eduError").classList.remove("hidden");
document.querySelector("#eduError div").innerHTML = json.error;
})); }));
}); });
document.querySelector("#goToCV").addEventListener("click", () => document.querySelector("#goToCV").addEventListener("click", () =>
{ {
textareaLoaded = false;
document.querySelector("#curriculumVitae").style.display = "block"; document.querySelector("#curriculumVitae").style.display = "block";
document.querySelector("#goToCV").classList.toggle("active"); document.querySelector("#goToCV").classList.add("active");
document.querySelector("#projects").style.display = "none"; document.querySelector("#projects").style.display = "none";
document.querySelector("#goToProjects").classList.toggle("active"); document.querySelector("#goToProjects").classList.remove("active");
}); });
document.querySelector("#goToProjects").addEventListener("click", () => document.querySelector("#goToProjects").addEventListener("click", () =>
{ {
textareaLoaded = false;
document.querySelector("#curriculumVitae").style.display = "none"; document.querySelector("#curriculumVitae").style.display = "none";
document.querySelector("#goToCV").classList.toggle("active"); document.querySelector("#goToCV").classList.remove("active");
document.querySelector("#projects").style.display = "block"; document.querySelector("#projects").style.display = "block";
document.querySelector("#goToProjects").classList.toggle("active"); document.querySelector("#goToProjects").classList.add("active");
}); });
document.querySelector("#logout").addEventListener("click", () => document.querySelector("#logout").addEventListener("click", () =>
{ {
document.cookie = "PHPSESSID=;Path=/cv;expires=Thu, 01 Jan 1970 00:00:01 GMT;"; fetch("/api/user/logout").then(res =>
window.location.reload(); {
if (res.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"));
/**
* 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 * Switches the timeline item between edit and view mode
* @param id the id of the timeline item * @param id the id of the timeline item from the database
*/ */
function edit(id) function editCVItem(id)
{ {
document.querySelector("#timelineItem" + id).classList.toggle("editing"); textareaLoaded = false;
document.querySelector(`#timelineItem${id}`).classList.toggle("editing");
if (id.includes("e")) if (id.includes("e"))
{ {
document.querySelector("#grade" + id).toggleAttribute("disabled"); document.querySelector(`#grade${id}`).toggleAttribute("disabled");
document.querySelector("#course" + id).toggleAttribute("disabled"); document.querySelector(`#course${id}`).toggleAttribute("disabled");
return; return;
} }
document.querySelector("#companyName" + id).toggleAttribute("disabled"); document.querySelector(`#companyName${id}`).toggleAttribute("disabled");
document.querySelector("#area" + id).toggleAttribute("disabled"); document.querySelector(`#area${id}`).toggleAttribute("disabled");
document.querySelector("#jobTitle" + id).toggleAttribute("disabled"); document.querySelector(`#jobTitle${id}`).toggleAttribute("disabled");
} }
/** /**
* Updates the education timeline item with the given id * Updates the education timeline item with the given id
* @param ID - the id of the course timeline item * @param {number} ID - the id of the course timeline item from the database
* @param startPeriod - the start date of the course * @param {string} startPeriod - the start date of the course
* @param endPeriod - the end date of the course * @param {string} endPeriod - the end date of the course
* @param grade - the grade of the course * @param {string} grade - the grade of the course
* @param course - the name of the course * @param {string} course - the name of the course
* @param prepend - whether to prepend the timeline item to the timeline * @param {boolean} prepend - whether to prepend the timeline item to the timeline
*/ */
function addEduData(ID, startPeriod, endPeriod, grade, course, prepend=false) function addEduData(ID, startPeriod, endPeriod, grade, course, prepend=false)
{ {
@ -209,7 +255,7 @@ function addEduData(ID, startPeriod, endPeriod, grade, course, prepend=false)
timelineItem.onsubmit = e => updateEduItem(ID, e); timelineItem.onsubmit = e => updateEduItem(ID, e);
timelineItem.innerHTML = ` timelineItem.innerHTML = `
<div class="modifyBtnContainer"> <div class="modifyBtnContainer">
<button class="edit" type="button" id="edit${id}" onclick="edit('${id}')"><i class="fa-solid fa-pen-to-square"></i></button> <button class="edit" type="button" id="edit${id}" onclick="editCVItem('${id}')"><i class="fa-solid fa-pen-to-square"></i></button>
<button class="delete" type="button" id="delete${id}" onclick="deleteEduItem(${ID})"><i class="fa-solid fa-trash"></i></button> <button class="delete" type="button" id="delete${id}" onclick="deleteEduItem(${ID})"><i class="fa-solid fa-trash"></i></button>
</div> </div>
<div class="dateContainer formControl"> <div class="dateContainer formControl">
@ -242,13 +288,13 @@ function addEduData(ID, startPeriod, endPeriod, grade, course, prepend=false)
/** /**
* Adds a new work timeline item to the page * Adds a new work timeline item to the page
* @param ID - the id of the work timeline item * @param {number} ID - the id of the work timeline item from the database
* @param startPeriod - the start date of the job * @param {string} startPeriod - the start date of the job
* @param endPeriod - the end date of the job * @param {string} endPeriod - the end date of the job
* @param companyName - the name of the company * @param {string} companyName - the name of the company
* @param area - the area of the company * @param {string} area - the area of the company
* @param jobTitle - the job title * @param {string} jobTitle - the job title
* @param prepend - whether to prepend the timeline item to the timeline * @param {boolean} prepend - whether to prepend the timeline item to the timeline
*/ */
function addWorkData(ID, startPeriod, endPeriod, companyName, area, jobTitle, prepend=false) function addWorkData(ID, startPeriod, endPeriod, companyName, area, jobTitle, prepend=false)
{ {
@ -259,7 +305,7 @@ function addWorkData(ID, startPeriod, endPeriod, companyName, area, jobTitle, pr
timelineItem.onsubmit = e => updateWorkItem(ID, e); timelineItem.onsubmit = e => updateWorkItem(ID, e);
timelineItem.innerHTML = ` timelineItem.innerHTML = `
<div class="modifyBtnContainer"> <div class="modifyBtnContainer">
<button class="edit" type="button" id="edit${id}" onclick="edit('${id}')"><i class="fa-solid fa-pen-to-square"></i></button> <button class="edit" type="button" id="edit${id}" onclick="editCVItem('${id}')"><i class="fa-solid fa-pen-to-square"></i></button>
<button class="delete" type="button" id="delete${id}" onclick="deleteWorkItem(${ID})"><i class="fa-solid fa-trash"></i></button> <button class="delete" type="button" id="delete${id}" onclick="deleteWorkItem(${ID})"><i class="fa-solid fa-trash"></i></button>
</div> </div>
<div class="dateContainer formControl"> <div class="dateContainer formControl">
@ -294,8 +340,9 @@ function addWorkData(ID, startPeriod, endPeriod, companyName, area, jobTitle, pr
/** /**
* Updates the edu timeline item with the given id * Updates the edu timeline item with the given id
* @param id the id of the edu timeline item * and data from the form
* @param e the event that triggered the function * @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) function updateEduItem(id, e)
{ {
@ -341,8 +388,9 @@ function updateEduItem(id, e)
/** /**
* Updates the work timeline item with the given id * Updates the work timeline item with the given id
* @param id the id of the work timeline item * and data from the form
* @param e the event that triggered the function * @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) function updateWorkItem(id, e)
{ {
@ -389,7 +437,7 @@ function updateWorkItem(id, e)
/** /**
* Deletes the timeline item with the given id * Deletes the timeline item with the given id
* @param id the id of the timeline item * @param {number} id the id of the timeline item
*/ */
function deleteEduItem(id) function deleteEduItem(id)
{ {
@ -417,7 +465,7 @@ function deleteEduItem(id)
/** /**
* Updates the timeline item with the given id * Updates the timeline item with the given id
* @param id the id of the timeline item * @param {number} id the id of the timeline item from the database
*/ */
function deleteWorkItem(id) function deleteWorkItem(id)
{ {
@ -444,21 +492,145 @@ function deleteWorkItem(id)
}); });
} }
/**
function addProject(information, projectLink, gitLink) * 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)
{ {
document.querySelector("#projList").innerHTML += ` e.preventDefault();
<div class="projItem"> let data = {}
<img src="../imgs/500x400.jpg" alt=""> data["title"] = document.querySelector(`#title${id}`).value;
<div class="flexCol"> data["isMainProject"] = document.querySelector(`#isMainProject${id}`).checked;
<div> data["img"] = document.querySelector(`#img${id}`).files[0];
<p>${information}</p> data["information"] = document.querySelector(`#info${id}`).value;
</div> data["projectLink"] = document.querySelector(`#viewProj${id}`).value;
<div> data["gitLink"] = document.querySelector(`#git${id}`).value;
<a href="${(projectLink === "N/A") ? "#" : projectLink}" class="btn btnPrimary boxShadowIn boxShadowOut"${(projectLink === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a>
<a href="${(gitLink === "N/A") ? "#" : gitLink}" class="btn btnOutline boxShadowIn boxShadowOut">${(gitLink === "N/A") ? "disabled=\"disabled\"" : ""}Github</a> fetch("/api/projectData/" + id, {
</div> method: "PATCH",
</div> body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + localStorage.getItem("token")
}
}).then(res =>
{
if (res.ok)
{
document.querySelector(`#projectItem${id}`).classList.toggle("editing");
document.querySelector(`#title${id}`).setAttribute("disabled", "");
document.querySelector(`#info${id}`).setAttribute("disabled", "");
return;
}
if (res.status === 401)
{
window.location.href = "./";
return;
}
res.json().then(json =>
{
document.querySelector(`#projectError${id}`).classList.remove("hidden");
document.querySelector(`#projectError${id} div`).innerHTML = json.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} 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)
{
let projectItem = document.createElement("form");
projectItem.id = "projectItem" + id;
projectItem.classList.add("projItem");
projectItem.onsubmit = e => updateProjectItem(id, e);
projectItem.innerHTML = `
<div class="modifyBtnContainer">
<button class="edit" type="button" id="edit${id}" onclick="editProjectItem(${id})"><i class="fa-solid fa-pen-to-square"></i></button>
<button class="delete" type="button" id="delete${id}" onclick="deleteProjectItem(${id})"><i class="fa-solid fa-trash"></i></button>
</div>
<img class="displayedImage" src="../imgs/500x400.jpg" alt="image preivew of the project">
<div class="formControl imageContainer">
<input type="file" name="img${id}" id="img${id}">
</div>
<div class="formControl projectTitleContainer">
<input type="text" name="title${id}" id="title${id}" value="${title}" disabled>
</div>
<div class="formControl isMainProject">
<label class="checkContainer" for="isMainProject${id}">Is It The Main Project
<input type="checkbox" id="isMainProject${id}" name="isMainProject${id}">
<span class="checkmark"></span>
</label>
</div>
<div class="formControl infoContainer">
<textarea name="info${id}" id="info${id}" disabled>${information}</textarea>
</div>
<div class="formControl viewProjContainer">
<input type="text" name="viewProj${id}" id="viewProj${id}" value="${projectLink}">
</div>
<div class="formControl gitContainer">
<input type="text" name="git${id}" id="git${id}" value="${gitLink}">
</div>
<div class="error hidden" id="projError${id}">
<button class="close" type="button" onclick="this.parentElement.classList.toggle('hidden');">&times;</button>
<div></div>
</div>
<input type="submit" value="Change">
<div class="linkContainer">
<a href="${(projectLink === "N/A") ? "#" : projectLink}" class="btn btnPrimary boxShadowIn boxShadowOut"${(projectLink === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a>
<a href="${(gitLink === "N/A") ? "#" : gitLink}" class="btn btnOutline boxShadowIn boxShadowOut">${(gitLink === "N/A") ? "disabled=\"disabled\"" : ""}Git</a>
</div> </div>
`; `;
document.querySelector("#projList").appendChild(projectItem);
} }

View File

@ -11,12 +11,23 @@ document.addEventListener("DOMContentLoaded", _ =>
}); });
}); });
/**
* 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) function showErrorMessage(message, form)
{ {
document.querySelector(`#${form}Error`).classList.remove("hidden"); document.querySelector(`#${form}Error`).classList.remove("hidden");
document.querySelector(`#${form}Error div`).innerText = message; document.querySelector(`#${form}Error div`).innerText = message;
} }
/**
* Switches between the different forms
* @param {string} from The css selector of form to switch from
* @param {string} to The css selector of form to switch to
*/
function switchView(from, to) function switchView(from, to)
{ {
document.querySelector(from).classList.toggle("shown"); document.querySelector(from).classList.toggle("shown");

View File

@ -176,7 +176,7 @@ function getProjectData()
<p>${item["information"]}</p> <p>${item["information"]}</p>
<div class="flexCol"> <div class="flexCol">
<a href="${(item["projectLink"] === "N/A") ? "#" : item["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut" ${(item["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a> <a href="${(item["projectLink"] === "N/A") ? "#" : item["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut" ${(item["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a>
<a href="${(item["gitLink"] === "N/A") ? "#" : item["gitLink"]}" class="btn btnOutline boxShadowIn boxShadowOut" ${(item["gitLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>GitHub</a> <a href="${(item["gitLink"] === "N/A") ? "#" : item["gitLink"]}" class="btn btnOutline boxShadowIn boxShadowOut" ${(item["gitLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>Git</a>
</div> </div>
</div> </div>
</div> </div>
@ -189,11 +189,12 @@ function getProjectData()
<img src="imgs/500x400.jpg" alt=""> <img src="imgs/500x400.jpg" alt="">
<div class="flexCol"> <div class="flexCol">
<div> <div>
<h3>${item["title"]}</h3>
<p>${item["information"]}</p> <p>${item["information"]}</p>
</div> </div>
<div> <div>
<a href="${(item["projectLink"] === "N/A") ? "#" : item["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut"${(item["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a> <a href="${(item["projectLink"] === "N/A") ? "#" : item["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut"${(item["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a>
<a href="${(item["githubLink"] === "N/A") ? "#" : item["gitubLink"]}" class="btn btnOutline boxShadowIn boxShadowOut">${(item["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Github</a> <a href="${(item["githubLink"] === "N/A") ? "#" : item["gitubLink"]}" class="btn btnOutline boxShadowIn boxShadowOut">${(item["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Git</a>
</div> </div>
</div> </div>
</div> </div>