Base HTML for projects section completed
Signed-off-by: rodude123 <rodude123@gmail.com>
This commit is contained in:
@@ -54,6 +54,8 @@ $app->get("/timelineData/{timeline}", function (Request $request, Response $resp
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// something went wrong
|
||||
$response->getBody()->write(json_encode(array("errorMessage" => "Error, timeline data not found")));
|
||||
return $response->withStatus(404);
|
||||
@@ -285,6 +287,7 @@ $app->post("/contact", function (Request $request, Response $response)
|
||||
{
|
||||
$response->getBody()->write(json_encode(array("errorMessage" => "Please fill out all the fields")));
|
||||
return $response->withStatus(400);
|
||||
|
||||
}
|
||||
|
||||
if (!filter_var($data["email"], FILTER_VALIDATE_EMAIL))
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
// middleware
|
||||
namespace api;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Slim\App;
|
||||
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
|
||||
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
|
||||
use Slim\Exception\HttpMethodNotAllowedException;
|
||||
use Slim\Exception\HttpNotFoundException;
|
||||
use Slim\Psr7\Response;
|
||||
use Tuupola\Middleware\JwtAuthentication;
|
||||
use Tuupola\Middleware\JwtAuthentication\RequestMethodRule;
|
||||
use Tuupola\Middleware\JwtAuthentication\RequestPathRule;
|
||||
@@ -24,6 +29,7 @@ class middleware
|
||||
$this->baseMiddleware($app);
|
||||
$this->sameSiteConfig($app);
|
||||
$this->jwtAuth($app);
|
||||
$this->errorHandling($app);
|
||||
$this->returnAsJSON($app);
|
||||
}
|
||||
|
||||
@@ -86,7 +92,31 @@ class middleware
|
||||
return $response->withStatus(401);
|
||||
}
|
||||
]));
|
||||
}
|
||||
|
||||
function errorHandling(App $app): void
|
||||
{
|
||||
$app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $handler->handle($request);
|
||||
}
|
||||
catch (HttpNotFoundException $httpException)
|
||||
{
|
||||
$response = (new Response())->withStatus(404);
|
||||
$response->getBody()->write(json_encode(array("status" => "404", "message" => $request->getUri()->getPath() . " not found")));
|
||||
return $response;
|
||||
}
|
||||
catch (HttpMethodNotAllowedException $httpException)
|
||||
{
|
||||
$response = (new Response())->withStatus(405);
|
||||
$response->getBody()->write(json_encode(array("status" => "405", "message" => "Method not allowed")));
|
||||
return $response;
|
||||
}
|
||||
});
|
||||
$app->addErrorMiddleware(true, true, true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ class projectData
|
||||
function getProjectData(): array
|
||||
{
|
||||
$conn = dbConn();
|
||||
$stmt = $conn->prepare("SELECT title, isMainProject, information, imgLocation, projectLink, githubLink FROM projects order by date LIMIT 4;");
|
||||
$stmt = $conn->prepare("SELECT title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects order by date LIMIT 4;");
|
||||
$stmt->execute();
|
||||
|
||||
// set the resulting array to associative
|
||||
|
||||
@@ -159,6 +159,10 @@ form .formControl input:not([type="submit"]) {
|
||||
|
||||
form .formControl {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
form input[type="submit"] {
|
||||
@@ -189,7 +193,8 @@ form .formControl input:not([type="submit"]).invalid:invalid:focus, form .formCo
|
||||
box-shadow: 0 4px 2px 0 var(--mutedBlack);
|
||||
}
|
||||
|
||||
form .formControl input:not([type="submit"]):focus, form .formControl textarea:focus {
|
||||
form .formControl input:not([type="submit"]):focus, form .formControl textarea:focus,
|
||||
form .formControl input:not([type="submit"]):hover, form .formControl textarea:hover {
|
||||
border: 4px solid var(--primaryHover);
|
||||
}
|
||||
|
||||
@@ -208,6 +213,90 @@ form .formControl input:not([type="submit"]):focus + i.fa-eye-slash {
|
||||
color: var(--primaryHover);
|
||||
}
|
||||
|
||||
form .formControl .checkContainer {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-bottom: 1.25em;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
form .formControl .checkContainer input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
form .formControl .checkContainer .checkmark {
|
||||
position: absolute;
|
||||
top: 1.25em;
|
||||
left: 0;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
background-color: var(--mutedGrey);
|
||||
}
|
||||
|
||||
form .formControl .checkContainer:hover input ~ .checkmark {
|
||||
background-color: var(--grey);
|
||||
}
|
||||
|
||||
form .formControl .checkContainer input:checked ~ .checkmark {
|
||||
background-color: var(--primaryDefault);
|
||||
}
|
||||
|
||||
form .formControl .checkContainer input:checked:hover ~ .checkmark {
|
||||
background-color: var(--primaryHover);
|
||||
}
|
||||
|
||||
form .formControl .checkContainer .checkmark:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
form .formControl .checkContainer input:checked ~ .checkmark:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
form .formControl .checkContainer .checkmark:after {
|
||||
left: 9px;
|
||||
top: 5px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 3px 3px 0;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
form .formControl input[type="file"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form .formControl input[type="file"]::file-selector-button {
|
||||
background-color: var(--primaryDefault);
|
||||
border: 0;
|
||||
border-right: 5px solid var(--mutedBlack);
|
||||
padding: 15px;
|
||||
margin-right: 20px;
|
||||
-webkit-transition: all .5s;
|
||||
-moz-transition: all .5s;
|
||||
-ms-transition: all .5s;
|
||||
-o-transition: all .5s;
|
||||
transition: all .5s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
form .formControl input[type="file"]:hover::file-selector-button {
|
||||
background-color: var(--primaryHover);
|
||||
}
|
||||
|
||||
section#about, section#curriculumVitae h1 {
|
||||
padding: 0 5rem;
|
||||
}
|
||||
}
|
||||
@@ -23,19 +23,27 @@ input[type="submit"] {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
div.editorContainer {
|
||||
div.editorContainer, div.projectsGrid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
align-items: flex-start;
|
||||
gap: 2em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div.editorContainer > * {
|
||||
div.editorContainer > *, div.projectsGrid > * {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
section#curriculumVitae {
|
||||
display: block;
|
||||
}
|
||||
|
||||
section#projects, section#settings {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.modifyBtnContainer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -147,3 +155,49 @@ section#curriculumVitae form.timelineItem:not(.editing) input[type=submit] {
|
||||
section#curriculumVitae form.timelineItem:not(.editing) div.companyAreaContainer input {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
section#projects #projList .projItem {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
border: 1px solid var(--grey);
|
||||
gap: 1em;
|
||||
box-shadow: 0 6px 4px 0 var(--mutedBlack);
|
||||
-webkit-border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
section#projects #projList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
section#projects #projList .projItem img {
|
||||
max-width: 15rem;
|
||||
width: 100%;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
section#projects .projItem .flexCol div:nth-child(2) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
gap: 3em;
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
section#projects .flexCol div:nth-child(2) .btn {
|
||||
padding: 0.25em 0.5em;
|
||||
}
|
||||
|
||||
#isMainProject {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
+39
-6
@@ -10,9 +10,10 @@
|
||||
<nav class="sideNav">
|
||||
<a href="#" class="closeBtn" id="navClose">×</a>
|
||||
<ul>
|
||||
<li><a href="#" class="active"><span><</span>CV<span>></span></a></li>
|
||||
<li><a href="#"><span><</span>Projects<span>></span></a></li>
|
||||
<li><a href="#"><span><</span>Settings<span>></span></a></li>
|
||||
<li><a href="#" id="goToCV" class="active"><span><</span>CV<span>></span></a></li>
|
||||
<li><a href="#" id="goToProjects"><span><</span>Projects<span>></span></a></li>
|
||||
<li><a href="#" id="goToSettings"><span><</span>Settings<span>></span></a></li>
|
||||
<li><a href="#" id="logout"><span><</span>Logout<span>></span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main class="editor" style="margin-left: 250px;">
|
||||
@@ -21,7 +22,7 @@
|
||||
|
||||
<h1>Editor</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<section id="curriculumVitae">
|
||||
<h2>curriculum vitae</h2>
|
||||
<div class="cvGrid">
|
||||
@@ -108,8 +109,40 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
section#projects>h2{projects}+div.
|
||||
|
||||
<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>
|
||||
|
||||
@@ -46,6 +46,22 @@ document.addEventListener('DOMContentLoaded', () =>
|
||||
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["information"], item["projectLink"], item["gitLink"]);
|
||||
})
|
||||
return;
|
||||
}
|
||||
document.querySelector("#projects").innerHTML = "No project data found";
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
document.querySelector("#navOpen").addEventListener("click", e =>
|
||||
@@ -134,6 +150,28 @@ document.querySelector("#addWork").addEventListener("submit", e =>
|
||||
}));
|
||||
});
|
||||
|
||||
document.querySelector("#goToCV").addEventListener("click", () =>
|
||||
{
|
||||
document.querySelector("#curriculumVitae").style.display = "block";
|
||||
document.querySelector("#goToCV").classList.toggle("active");
|
||||
document.querySelector("#projects").style.display = "none";
|
||||
document.querySelector("#goToProjects").classList.toggle("active");
|
||||
});
|
||||
|
||||
document.querySelector("#goToProjects").addEventListener("click", () =>
|
||||
{
|
||||
document.querySelector("#curriculumVitae").style.display = "none";
|
||||
document.querySelector("#goToCV").classList.toggle("active");
|
||||
document.querySelector("#projects").style.display = "block";
|
||||
document.querySelector("#goToProjects").classList.toggle("active");
|
||||
});
|
||||
|
||||
document.querySelector("#logout").addEventListener("click", () =>
|
||||
{
|
||||
document.cookie = "PHPSESSID=;Path=/cv;expires=Thu, 01 Jan 1970 00:00:01 GMT;";
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Switches the timeline item between edit and view mode
|
||||
@@ -405,3 +443,22 @@ function deleteWorkItem(id)
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function addProject(information, projectLink, gitLink)
|
||||
{
|
||||
document.querySelector("#projList").innerHTML += `
|
||||
<div class="projItem">
|
||||
<img src="../imgs/500x400.jpg" alt="">
|
||||
<div class="flexCol">
|
||||
<div>
|
||||
<p>${information}</p>
|
||||
</div>
|
||||
<div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ function getProjectData()
|
||||
<p>${item["information"]}</p>
|
||||
<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["githubLink"] === "N/A") ? "#" : item["gitubLink"]}" class="btn btnOutline boxShadowIn boxShadowOut" ${(item["githubLink"] === "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\"" : ""}>GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user