Fixed some bugs in the newsletter images, made some minor improvements in other areas. Added in unsubscribe functionality #52
33
dist/api/blog/blogData.php
vendored
33
dist/api/blog/blogData.php
vendored
@ -296,17 +296,18 @@ class blogData
|
|||||||
$latest = $this->getLatestBlogPost();
|
$latest = $this->getLatestBlogPost();
|
||||||
$prevTitle = $latest["title"];
|
$prevTitle = $latest["title"];
|
||||||
$prevAbstract = $latest["abstract"];
|
$prevAbstract = $latest["abstract"];
|
||||||
$prevHeaderImage = $latest["headerImg"];
|
$prevHeaderImage = substr($latest["headerImg"], 10);
|
||||||
|
$prevHeaderImage = str_ireplace("%2F", "/", $prevHeaderImage);
|
||||||
|
|
||||||
$headerImage = $targetFile["imgLocation"];
|
$headerImage = rawurlencode("../" . $targetFile["imgLocation"]);
|
||||||
|
|
||||||
$stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, abstract, body, bodyText, categories, keywords, folderID)
|
$stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, abstract, body, bodyText, categories, keywords, folderID)
|
||||||
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :abstract, :body, :bodyText, :categories, :keywords, :folderID);");
|
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :abstract, :body, :bodyText, :categories, :keywords, :folderID);");
|
||||||
$stmt->bindParam(":title", $title);
|
$stmt->bindParam(":title", $title);
|
||||||
$stmt->bindParam(":dateCreated", $dateCreated);
|
$stmt->bindParam(":dateCreated", $dateCreated);
|
||||||
$stmt->bindParam(":dateModified", $dateCreated);
|
$stmt->bindParam(":dateModified", $dateCreated);
|
||||||
$isFeatured = $featured ? 1 : 0;
|
// $isFeatured = $featured ? 1 : 0;
|
||||||
$stmt->bindParam(":featured", $isFeatured);
|
$stmt->bindParam(":featured", $featured);
|
||||||
$stmt->bindParam(":headerImg", $headerImage);
|
$stmt->bindParam(":headerImg", $headerImage);
|
||||||
$stmt->bindParam(":abstract", $abstract);
|
$stmt->bindParam(":abstract", $abstract);
|
||||||
$stmt->bindParam(":body", $newBody);
|
$stmt->bindParam(":body", $newBody);
|
||||||
@ -323,6 +324,8 @@ class blogData
|
|||||||
$stmtEmails = $conn->prepare("SELECT email FROM newsletter;");
|
$stmtEmails = $conn->prepare("SELECT email FROM newsletter;");
|
||||||
$stmtEmails->execute();
|
$stmtEmails->execute();
|
||||||
$emails = $stmtEmails->fetchAll(PDO::FETCH_ASSOC);
|
$emails = $stmtEmails->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$headerImage = substr($headerImage, 10);
|
||||||
|
$headerImage = str_ireplace("%2F", "/", $headerImage);
|
||||||
|
|
||||||
$emailBody = <<<EOD
|
$emailBody = <<<EOD
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -533,7 +536,7 @@ class blogData
|
|||||||
<div class="postContainer">
|
<div class="postContainer">
|
||||||
<h2>latest post</h2>
|
<h2>latest post</h2>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img src="$headerImage" alt="header image of the latest post">
|
<img src="https://rohitpai.co.uk/$headerImage" alt="header image of the latest post">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="post">
|
<div class="post">
|
||||||
@ -546,7 +549,7 @@ class blogData
|
|||||||
<div class="postContainer">
|
<div class="postContainer">
|
||||||
<h2>in case you missed the previous post</h2>
|
<h2>in case you missed the previous post</h2>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img src="$prevHeaderImage" alt="header image of the previous post">
|
<img src="https://rohitpai.co.uk/$prevHeaderImage" alt="header image of the previous post">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="post">
|
<div class="post">
|
||||||
@ -556,21 +559,26 @@ class blogData
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
EOD;
|
||||||
|
|
||||||
|
foreach ($emails as $email)
|
||||||
|
{
|
||||||
|
$emailFooter = <<<EOD
|
||||||
<footer>
|
<footer>
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
||||||
<li><a href="https://rohitpai.co.uk/blog/unsubscribe"><Unsubscribe></a></li>
|
<li><a href="https://rohitpai.co.uk/blog/unsubscribe/$email"><Unsubscribe></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="date">2023</div>
|
<div class="date">2023</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
EOD;
|
EOD;
|
||||||
|
$emailBody .= $emailFooter;
|
||||||
|
|
||||||
foreach ($emails as $email)
|
|
||||||
{
|
|
||||||
$this->sendMail($email["email"], $emailBody, "Hey, Rohit's blog has a new post!");
|
$this->sendMail($email["email"], $emailBody, "Hey, Rohit's blog has a new post!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,7 +650,8 @@ EOD;
|
|||||||
unlink($result["headerImg"]);
|
unlink($result["headerImg"]);
|
||||||
$stmt = $conn->prepare("UPDATE blog SET headerImg = :headerImg WHERE ID = :ID;");
|
$stmt = $conn->prepare("UPDATE blog SET headerImg = :headerImg WHERE ID = :ID;");
|
||||||
$stmt->bindParam(":ID", $ID);
|
$stmt->bindParam(":ID", $ID);
|
||||||
$stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
|
$location = urldecode("../" . $targetFile["imgLocation"]);
|
||||||
|
$stmt->bindParam(":headerImg", $location);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
if ($stmt->rowCount() > 0)
|
if ($stmt->rowCount() > 0)
|
||||||
{
|
{
|
||||||
@ -1168,7 +1177,7 @@ EOD;
|
|||||||
<div class="nav">
|
<div class="nav">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
||||||
<li><a href="https://rohitpai.co.uk/blog/unsubscribe"><Unsubscribe></a></li>
|
<li><a href="https://rohitpai.co.uk/blog/unsubscribe/$email"><Unsubscribe></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="date">2023</div>
|
<div class="date">2023</div>
|
||||||
|
9
dist/api/blog/blogRoutes.php
vendored
9
dist/api/blog/blogRoutes.php
vendored
@ -282,17 +282,18 @@ class blogRoutes implements routesInterface
|
|||||||
if ($message === "email not found")
|
if ($message === "email not found")
|
||||||
{
|
{
|
||||||
// uh oh something went wrong
|
// uh oh something went wrong
|
||||||
$response->getBody()->write(json_encode(array("error" => "Error, email not found")));
|
$response->getBody()->write(json_encode(array("message" => "Woah, you're already trying to leave without signing up?")));
|
||||||
return $response->withStatus(404);
|
return $response->withStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message === "error")
|
if ($message === "error")
|
||||||
{
|
{
|
||||||
// uh oh something went wrong
|
// uh oh something went wrong
|
||||||
$response->getBody()->write(json_encode(array("error" => "Error, something went wrong")));
|
$response->getBody()->write(json_encode(array("message" => "Error, something went wrong")));
|
||||||
return $response->withStatus(500);
|
return $response->withStatus(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$response->getBody()->write(json_encode(array("message" => "Sorry to see you go! You'll no longer receive any emails from me. If you change your mind, you can always sign up again.")));
|
||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -324,8 +325,8 @@ class blogRoutes implements routesInterface
|
|||||||
$headerImg = null;
|
$headerImg = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$featured = $data["featured"] === "true";
|
// $featured = $data["featured"] === "true";
|
||||||
$insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
|
$insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], intval($data["featured"]), $data["categories"], $headerImg);
|
||||||
if (!is_int($insertedID))
|
if (!is_int($insertedID))
|
||||||
{
|
{
|
||||||
// uh oh something went wrong
|
// uh oh something went wrong
|
||||||
|
2
dist/blog/css/main.css
vendored
2
dist/blog/css/main.css
vendored
File diff suppressed because one or more lines are too long
2
dist/blog/index.html
vendored
2
dist/blog/index.html
vendored
@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Rohit Pai - Blog</title><meta name="title" content="Rohit Pai - Blog"><meta name="description" content="This is all the blog posts that Rohit Pai has posted. You'll find posts on various topics, mostly on tech but some on various other random topics."><meta name="keywords" content="Blog, all posts, rohit, pai, rohit pai, tech, web development, self-hosting, hosting"><meta name="robots" content="index, follow"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="language" content="English"><meta name="author" content="Rohit Pai"><link rel="stylesheet" href="/blog/css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script><script type="text/javascript" src="https://platform-api.sharethis.com/js/sharethis.js#property=6550cdc47a115e0012964576&product=sop" async="async"></script></head><body><nav><input type="checkbox" id="nav-check"><h1><a href="/" class="link">rohit pai</a></h1><div class="nav-btn"><label for="nav-check"><span></span> <span></span> <span></span></label></div><ul><li><a href="/#about" class="textShadow link">about</a></li><li><a href="/#curriculumVitae" class="textShadow link">cv</a></li><li><a href="/#projects" class="textShadow link">projects</a></li><li><a href="/#contact" class="textShadow link">contact</a></li><li><a href="/blog" class="textShadow link active">blog</a></li></ul></nav><header><div><h1>full stack developer</h1><a href="/#sayHello" class="btn btnPrimary boxShadowIn boxShadowOut">Contact Me</a> <a href="" id="arrow"><i class="fa-solid fa-chevron-down"></i></a></div></header><div class="menuBar"><div class="menu"><ul><li><a href="/blog" class="link active">All posts</a></li><li><a href="/blog/category" class="link">categories</a></li><li><label for="searchField" aria-hidden="true" hidden>search</label> <input type="search" name="search" id="searchField" placeholder="Search..."> <button type="submit" id="searchBtn" class="btn btnPrimary"><i class="fa fa-search"></i></button></li></ul></div></div><main id="main"></main><div class="modal-container" id="cookiePopup"><div class="modal"><div class="modal-content"><h2><i class="fas fa-cookie-bite"></i> Hey I use cookies btw</h2><p>Just to let you know, I use cookies to give you the best experience on my blog. By clicking agree I'll assume that you are happy with it. <a href="/blog/policy/cookie" class="link">Read more</a></p><div class="flexRow"><button class="btn btnPrimary" id="cookieAccept">agree</button> <a href="https://google.co.uk" class="btn btnPrimary">disagree</a></div></div></div></div><footer class="flexRow"><div class="nav"><ul><li><a href="/blog/policy/privacy" class="link">privacy policy</a></li><li><a href="/blog/policy/cookie" class="link">cookie policy</a></li></ul></div><p>© <span id="year"></span> Rohit Pai all rights reserved</p><div class="button"><button id="goBackToTop"><i class="fa-solid fa-chevron-up"></i></button></div></footer><script src="/js/typewriter.js"></script><script src="/blog/js/index.js"></script><script id="dsq-count-scr" src="https://rohitpaiportfolio.disqus.com/count.js" async></script></body></html>
|
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Rohit Pai - Blog</title><meta name="title" content="Rohit Pai - Blog"><meta name="description" content="This is all the blog posts that Rohit Pai has posted. You'll find posts on various topics, mostly on tech but some on various other random topics."><meta name="keywords" content="Blog, all posts, rohit, pai, rohit pai, tech, web development, self-hosting, hosting"><meta name="robots" content="index, follow"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="language" content="English"><meta name="author" content="Rohit Pai"><link rel="stylesheet" href="/blog/css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script><script type="text/javascript" src="https://platform-api.sharethis.com/js/sharethis.js#property=6550cdc47a115e0012964576&product=sop" async="async"></script></head><body><nav><input type="checkbox" id="nav-check"><h1><a href="/" class="link">rohit pai</a></h1><div class="nav-btn"><label for="nav-check"><span></span> <span></span> <span></span></label></div><ul><li><a href="/#about" class="textShadow link">about</a></li><li><a href="/#curriculumVitae" class="textShadow link">cv</a></li><li><a href="/#projects" class="textShadow link">projects</a></li><li><a href="/#contact" class="textShadow link">contact</a></li><li><a href="/blog" class="textShadow link active">blog</a></li></ul></nav><header><div><h1>full stack developer</h1><a href="/#sayHello" class="btn btnPrimary boxShadowIn boxShadowOut">Contact Me</a> <a href="" id="arrow"><i class="fa-solid fa-chevron-down"></i></a></div></header><div class="menuBar"><div class="menu"><ul><li><a href="/blog" class="link active">All posts</a></li><li><a href="/blog/category" class="link">categories</a></li><li><label for="searchField" aria-hidden="true" hidden>search</label> <input type="search" name="search" id="searchField" placeholder="Search..."> <button type="submit" id="searchBtn" class="btn btnPrimary"><i class="fa fa-search"></i></button></li></ul></div></div><main id="main"></main><div class="modal-container" id="cookiePopup"><div class="modal"><div class="modal-content"><h2><i class="fas fa-cookie-bite"></i> Hey I use cookies btw</h2><p>Just to let you know, I use cookies to give you the best experience on my blog. By clicking agree I'll assume that you are happy with it. <a href="/blog/policy/cookie" class="link">Read more</a></p><div class="flexRow"><button class="btn btnPrimary" id="cookieAccept">agree</button></div></div></div></div><footer class="flexRow"><div class="nav"><ul><li><a href="/blog/policy/privacy" class="link">privacy policy</a></li><li><a href="/blog/policy/cookie" class="link">cookie policy</a></li></ul></div><p>© <span id="year"></span> Rohit Pai all rights reserved</p><div class="button"><button id="goBackToTop"><i class="fa-solid fa-chevron-up"></i></button></div></footer><script src="/js/typewriter.js"></script><script src="/blog/js/index.js"></script><script id="dsq-count-scr" src="https://rohitpaiportfolio.disqus.com/count.js" async></script></body></html>
|
2
dist/blog/js/index.js
vendored
2
dist/blog/js/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/css/main.css
vendored
2
dist/css/main.css
vendored
File diff suppressed because one or more lines are too long
2
dist/editor/css/main.css
vendored
2
dist/editor/css/main.css
vendored
File diff suppressed because one or more lines are too long
@ -296,17 +296,18 @@ class blogData
|
|||||||
$latest = $this->getLatestBlogPost();
|
$latest = $this->getLatestBlogPost();
|
||||||
$prevTitle = $latest["title"];
|
$prevTitle = $latest["title"];
|
||||||
$prevAbstract = $latest["abstract"];
|
$prevAbstract = $latest["abstract"];
|
||||||
$prevHeaderImage = $latest["headerImg"];
|
$prevHeaderImage = substr($latest["headerImg"], 10);
|
||||||
|
$prevHeaderImage = str_ireplace("%2F", "/", $prevHeaderImage);
|
||||||
|
|
||||||
$headerImage = $targetFile["imgLocation"];
|
$headerImage = rawurlencode("../" . $targetFile["imgLocation"]);
|
||||||
|
|
||||||
$stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, abstract, body, bodyText, categories, keywords, folderID)
|
$stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, abstract, body, bodyText, categories, keywords, folderID)
|
||||||
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :abstract, :body, :bodyText, :categories, :keywords, :folderID);");
|
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :abstract, :body, :bodyText, :categories, :keywords, :folderID);");
|
||||||
$stmt->bindParam(":title", $title);
|
$stmt->bindParam(":title", $title);
|
||||||
$stmt->bindParam(":dateCreated", $dateCreated);
|
$stmt->bindParam(":dateCreated", $dateCreated);
|
||||||
$stmt->bindParam(":dateModified", $dateCreated);
|
$stmt->bindParam(":dateModified", $dateCreated);
|
||||||
$isFeatured = $featured ? 1 : 0;
|
// $isFeatured = $featured ? 1 : 0;
|
||||||
$stmt->bindParam(":featured", $isFeatured);
|
$stmt->bindParam(":featured", $featured);
|
||||||
$stmt->bindParam(":headerImg", $headerImage);
|
$stmt->bindParam(":headerImg", $headerImage);
|
||||||
$stmt->bindParam(":abstract", $abstract);
|
$stmt->bindParam(":abstract", $abstract);
|
||||||
$stmt->bindParam(":body", $newBody);
|
$stmt->bindParam(":body", $newBody);
|
||||||
@ -323,6 +324,8 @@ class blogData
|
|||||||
$stmtEmails = $conn->prepare("SELECT email FROM newsletter;");
|
$stmtEmails = $conn->prepare("SELECT email FROM newsletter;");
|
||||||
$stmtEmails->execute();
|
$stmtEmails->execute();
|
||||||
$emails = $stmtEmails->fetchAll(PDO::FETCH_ASSOC);
|
$emails = $stmtEmails->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
$headerImage = substr($headerImage, 10);
|
||||||
|
$headerImage = str_ireplace("%2F", "/", $headerImage);
|
||||||
|
|
||||||
$emailBody = <<<EOD
|
$emailBody = <<<EOD
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@ -533,7 +536,7 @@ class blogData
|
|||||||
<div class="postContainer">
|
<div class="postContainer">
|
||||||
<h2>latest post</h2>
|
<h2>latest post</h2>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img src="$headerImage" alt="header image of the latest post">
|
<img src="https://rohitpai.co.uk/$headerImage" alt="header image of the latest post">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="post">
|
<div class="post">
|
||||||
@ -546,7 +549,7 @@ class blogData
|
|||||||
<div class="postContainer">
|
<div class="postContainer">
|
||||||
<h2>in case you missed the previous post</h2>
|
<h2>in case you missed the previous post</h2>
|
||||||
<div class="image">
|
<div class="image">
|
||||||
<img src="$prevHeaderImage" alt="header image of the previous post">
|
<img src="https://rohitpai.co.uk/$prevHeaderImage" alt="header image of the previous post">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="post">
|
<div class="post">
|
||||||
@ -556,21 +559,26 @@ class blogData
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
EOD;
|
||||||
|
|
||||||
|
foreach ($emails as $email)
|
||||||
|
{
|
||||||
|
$emailFooter = <<<EOD
|
||||||
<footer>
|
<footer>
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
||||||
<li><a href="https://rohitpai.co.uk/blog/unsubscribe"><Unsubscribe></a></li>
|
<li><a href="https://rohitpai.co.uk/blog/unsubscribe/$email"><Unsubscribe></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="date">2023</div>
|
<div class="date">2023</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
EOD;
|
EOD;
|
||||||
|
$emailBody .= $emailFooter;
|
||||||
|
|
||||||
foreach ($emails as $email)
|
|
||||||
{
|
|
||||||
$this->sendMail($email["email"], $emailBody, "Hey, Rohit's blog has a new post!");
|
$this->sendMail($email["email"], $emailBody, "Hey, Rohit's blog has a new post!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,7 +650,8 @@ EOD;
|
|||||||
unlink($result["headerImg"]);
|
unlink($result["headerImg"]);
|
||||||
$stmt = $conn->prepare("UPDATE blog SET headerImg = :headerImg WHERE ID = :ID;");
|
$stmt = $conn->prepare("UPDATE blog SET headerImg = :headerImg WHERE ID = :ID;");
|
||||||
$stmt->bindParam(":ID", $ID);
|
$stmt->bindParam(":ID", $ID);
|
||||||
$stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
|
$location = urldecode("../" . $targetFile["imgLocation"]);
|
||||||
|
$stmt->bindParam(":headerImg", $location);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
if ($stmt->rowCount() > 0)
|
if ($stmt->rowCount() > 0)
|
||||||
{
|
{
|
||||||
@ -1168,7 +1177,7 @@ EOD;
|
|||||||
<div class="nav">
|
<div class="nav">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
<li><a href="https://rohitpai.co.uk/blog"><https://rohitpai.co.uk/blog></a></li>
|
||||||
<li><a href="https://rohitpai.co.uk/blog/unsubscribe"><Unsubscribe></a></li>
|
<li><a href="https://rohitpai.co.uk/blog/unsubscribe/$email"><Unsubscribe></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="date">2023</div>
|
<div class="date">2023</div>
|
||||||
|
@ -282,17 +282,18 @@ class blogRoutes implements routesInterface
|
|||||||
if ($message === "email not found")
|
if ($message === "email not found")
|
||||||
{
|
{
|
||||||
// uh oh something went wrong
|
// uh oh something went wrong
|
||||||
$response->getBody()->write(json_encode(array("error" => "Error, email not found")));
|
$response->getBody()->write(json_encode(array("message" => "Woah, you're already trying to leave without signing up?")));
|
||||||
return $response->withStatus(404);
|
return $response->withStatus(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($message === "error")
|
if ($message === "error")
|
||||||
{
|
{
|
||||||
// uh oh something went wrong
|
// uh oh something went wrong
|
||||||
$response->getBody()->write(json_encode(array("error" => "Error, something went wrong")));
|
$response->getBody()->write(json_encode(array("message" => "Error, something went wrong")));
|
||||||
return $response->withStatus(500);
|
return $response->withStatus(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$response->getBody()->write(json_encode(array("message" => "Sorry to see you go! You'll no longer receive any emails from me. If you change your mind, you can always sign up again.")));
|
||||||
return $response;
|
return $response;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -324,8 +325,8 @@ class blogRoutes implements routesInterface
|
|||||||
$headerImg = null;
|
$headerImg = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$featured = $data["featured"] === "true";
|
// $featured = $data["featured"] === "true";
|
||||||
$insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
|
$insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], intval($data["featured"]), $data["categories"], $headerImg);
|
||||||
if (!is_int($insertedID))
|
if (!is_int($insertedID))
|
||||||
{
|
{
|
||||||
// uh oh something went wrong
|
// uh oh something went wrong
|
||||||
|
@ -79,7 +79,7 @@ article a {
|
|||||||
|
|
||||||
article a::before,
|
article a::before,
|
||||||
article a::after {
|
article a::after {
|
||||||
visibility: hidden;
|
visibility: visible;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
@ -93,9 +93,9 @@ article a::after {
|
|||||||
content: '>';
|
content: '>';
|
||||||
}
|
}
|
||||||
|
|
||||||
article a:hover::before,
|
article a:hover,
|
||||||
article a:hover::after {
|
article a:hover {
|
||||||
visibility: visible;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
article h1 {
|
article h1 {
|
||||||
@ -106,6 +106,10 @@ article h3 {
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article h3:not(div.byLine > h3), .otherPosts h3 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
aside.sideContent {
|
aside.sideContent {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -108,14 +108,18 @@ section.largePost .outerContent .postContent a {
|
|||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
#main .errorFof {
|
#main .errorFof, #main .unsubscribe {
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100dvh;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fof {
|
#main .unsubscribe {
|
||||||
|
height: 50dvh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centered {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,6 @@
|
|||||||
</p>
|
</p>
|
||||||
<div class="flexRow">
|
<div class="flexRow">
|
||||||
<button class="btn btnPrimary" id="cookieAccept">agree</button>
|
<button class="btn btnPrimary" id="cookieAccept">agree</button>
|
||||||
<a href="https://google.co.uk" class="btn btnPrimary">disagree</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,7 +38,7 @@ function goToURL(url)
|
|||||||
document.querySelector('#cookiePopup').classList.add('hidden');
|
document.querySelector('#cookiePopup').classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url === '/blog/' || url === '/blog')
|
if (url === '/blog' || url === 'blog')
|
||||||
{
|
{
|
||||||
loadHomeContent();
|
loadHomeContent();
|
||||||
// window.history.pushState(null, null, url);
|
// window.history.pushState(null, null, url);
|
||||||
@ -88,6 +88,15 @@ function goToURL(url)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (urlArray[2] === 'unsubscribe')
|
||||||
|
{
|
||||||
|
if (urlArray[3])
|
||||||
|
{
|
||||||
|
unsubscribe(urlArray[urlArray.length - 1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
show404();
|
show404();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +145,7 @@ function submitNewsletter()
|
|||||||
{
|
{
|
||||||
document.querySelector('#newsletterMessage').classList.add('error');
|
document.querySelector('#newsletterMessage').classList.add('error');
|
||||||
document.querySelector('#newsletterMessage').classList.remove('success');
|
document.querySelector('#newsletterMessage').classList.remove('success');
|
||||||
document.querySelector('#newsletterMessage div').innerHTML = 'You\'ve already signed up you silly goose!';
|
document.querySelector('#newsletterMessage div').innerHTML = 'You"ve already signed up you silly goose!';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +162,31 @@ function submitNewsletter()
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unsubscribe(email)
|
||||||
|
{
|
||||||
|
fetch(`/api/blog/newsletter/${email}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
}).then(res => res.json().then(json =>
|
||||||
|
{
|
||||||
|
document.querySelector('#main').innerHTML = '';
|
||||||
|
let post = document.createElement('section');
|
||||||
|
post.classList.add('unsubscribe');
|
||||||
|
post.id = 'unsubscribe';
|
||||||
|
let mainContent = document.createElement('div');
|
||||||
|
mainContent.classList.add('centered');
|
||||||
|
mainContent.innerHTML = `
|
||||||
|
<h1>Unsubscribe</h1>
|
||||||
|
<p>${json.message}</p>
|
||||||
|
<a href="/blog/" class="btn btnPrimary">See all blog posts</a>
|
||||||
|
`;
|
||||||
|
post.appendChild(mainContent);
|
||||||
|
document.querySelector('#main').appendChild(post);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a formatted date
|
* Creates a formatted date
|
||||||
* @param {string} dateString - the date string
|
* @param {string} dateString - the date string
|
||||||
@ -175,7 +209,7 @@ function createLargePost(post)
|
|||||||
outerContent.classList.add('outerContent');
|
outerContent.classList.add('outerContent');
|
||||||
let img = document.createElement('img');
|
let img = document.createElement('img');
|
||||||
img.className = 'banner';
|
img.className = 'banner';
|
||||||
img.src = post.headerImg;
|
img.src = post.headerImg.replaceAll('%2F', '/');
|
||||||
img.alt = post.title;
|
img.alt = post.title;
|
||||||
outerContent.appendChild(img);
|
outerContent.appendChild(img);
|
||||||
let content = document.createElement('div');
|
let content = document.createElement('div');
|
||||||
@ -464,7 +498,7 @@ function createMetaTag(nameOrProperty, attribute, value)
|
|||||||
*/
|
*/
|
||||||
function insertMetaTags(json)
|
function insertMetaTags(json)
|
||||||
{
|
{
|
||||||
let metaDesc = document.querySelector('meta[name="description"]');
|
let metaDesc = document.querySelector('meta[name=\'description\']');
|
||||||
metaDesc.setAttribute('content', json.abstract);
|
metaDesc.setAttribute('content', json.abstract);
|
||||||
|
|
||||||
// Twitter meta tags
|
// Twitter meta tags
|
||||||
@ -478,11 +512,11 @@ function insertMetaTags(json)
|
|||||||
createMetaTag('og:image', 'content', json.headerImg);
|
createMetaTag('og:image', 'content', json.headerImg);
|
||||||
createMetaTag('og:url', 'content', window.location.href);
|
createMetaTag('og:url', 'content', window.location.href);
|
||||||
createMetaTag('og:type', 'content', 'blog');
|
createMetaTag('og:type', 'content', 'blog');
|
||||||
createMetaTag('og:site_name', 'content', 'Rohit Pai\'s Blog');
|
createMetaTag('og:site_name', 'content', 'Rohit Pai"s Blog');
|
||||||
createMetaTag('og:locale', 'content', 'en_GB');
|
createMetaTag('og:locale', 'content', 'en_GB');
|
||||||
|
|
||||||
//Keywords
|
//Keywords
|
||||||
let metKeywords = document.querySelector('meta[name="keywords"]');
|
let metKeywords = document.querySelector('meta[name=\'keywords\']');
|
||||||
let keywords = metKeywords.getAttribute('content');
|
let keywords = metKeywords.getAttribute('content');
|
||||||
keywords += `, ${json.keywords}`;
|
keywords += `, ${json.keywords}`;
|
||||||
metKeywords.setAttribute('content', keywords);
|
metKeywords.setAttribute('content', keywords);
|
||||||
@ -515,6 +549,7 @@ async function loadIndividualPost(title)
|
|||||||
let mainContent = document.createElement('div');
|
let mainContent = document.createElement('div');
|
||||||
mainContent.classList.add('mainContent');
|
mainContent.classList.add('mainContent');
|
||||||
let article = document.createElement('article');
|
let article = document.createElement('article');
|
||||||
|
let headerImg = json.headerImg.replaceAll('%2F', '/');
|
||||||
article.innerHTML = `
|
article.innerHTML = `
|
||||||
<h1>${json.title}</h1>
|
<h1>${json.title}</h1>
|
||||||
<div class="byLine">
|
<div class="byLine">
|
||||||
@ -522,9 +557,9 @@ async function loadIndividualPost(title)
|
|||||||
<h3>${createButtonCategories([csvToArray(json.categories.replace(/\s*,\s*/g, ','))])}</h3>
|
<h3>${createButtonCategories([csvToArray(json.categories.replace(/\s*,\s*/g, ','))])}</h3>
|
||||||
<div class="sharethis-inline-share-buttons" data-url="https://rohitpai.co.uk/blog/post/${title}"
|
<div class="sharethis-inline-share-buttons" data-url="https://rohitpai.co.uk/blog/post/${title}"
|
||||||
data-title="${json.title}" data-description="${json.abstract}"
|
data-title="${json.title}" data-description="${json.abstract}"
|
||||||
data-image="https://rohitpai.co.uk/${json.headerImg}" data-username="@rohitpai123"></div>
|
data-image="https://rohitpai.co.uk/${headerImg}" data-username="@rohitpai123"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cover" style="background-image: url('${json.headerImg}')"></div>
|
<div class="cover" style="background-image: url('${headerImg}')"></div>
|
||||||
${json.body}
|
${json.body}
|
||||||
`;
|
`;
|
||||||
let comments = document.createElement('section');
|
let comments = document.createElement('section');
|
||||||
@ -662,7 +697,7 @@ function loadPrivacyPolicy()
|
|||||||
<h2>Privacy Policy</h2>
|
<h2>Privacy Policy</h2>
|
||||||
<p>Last Updated: Nov 12, 2023</p>
|
<p>Last Updated: Nov 12, 2023</p>
|
||||||
<p>
|
<p>
|
||||||
Thank you for visiting the Privacy Policy of Rohit Pai's Blog. This Privacy Policy explains how I, Rohit Pai, collect, use, and share information about you (“you”, “yours” or “user”) when you access or use my website (“Services”). You are responsible for any third-party data you provide or share through the Services and confirm that you have the third party's consent to provide such data to me.
|
Thank you for visiting the Privacy Policy of Rohit Pai"s Blog. This Privacy Policy explains how I, Rohit Pai, collect, use, and share information about you (“you”, “yours” or “user”) when you access or use my website (“Services”). You are responsible for any third-party data you provid'e or share through the Services and confirm that you have the third partys consent to provide such data to me.
|
||||||
</p>
|
</p>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -833,7 +868,7 @@ function show404()
|
|||||||
{
|
{
|
||||||
document.querySelector('#main').innerHTML = `
|
document.querySelector('#main').innerHTML = `
|
||||||
<div class="errorFof">
|
<div class="errorFof">
|
||||||
<div class="fof">
|
<div class="centered">
|
||||||
<h1>Blog post, Category or page not found</h1>
|
<h1>Blog post, Category or page not found</h1>
|
||||||
<a href="/blog/" class="btn btnPrimary">See all blog posts</a>
|
<a href="/blog/" class="btn btnPrimary">See all blog posts</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -334,11 +334,18 @@ a.link {
|
|||||||
|
|
||||||
a.link::before,
|
a.link::before,
|
||||||
a.link::after {
|
a.link::after {
|
||||||
visibility: hidden;
|
visibility: visible;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nav a.link::before,
|
||||||
|
nav a.link::after,
|
||||||
|
.nav a.link::before,
|
||||||
|
.nav a.link::after {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
a.link::before {
|
a.link::before {
|
||||||
content: ' <';
|
content: ' <';
|
||||||
margin-left: -0.5em;
|
margin-left: -0.5em;
|
||||||
@ -348,11 +355,21 @@ a.link::after {
|
|||||||
content: '> ';
|
content: '> ';
|
||||||
}
|
}
|
||||||
|
|
||||||
a.link:hover::before,
|
a.link:hover {
|
||||||
a.link:hover::after {
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.link:hover::before,
|
||||||
|
nav a.link:hover::after,
|
||||||
|
.nav a.link:hover::before,
|
||||||
|
.nav a.link:hover::after {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nav a.link:hover, .nav a.link:hover {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
div.error, div.success {
|
div.error, div.success {
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
padding: 0.5em 0.8em;
|
padding: 0.5em 0.8em;
|
||||||
|
@ -234,7 +234,7 @@ section#projects form.projItem:not(.editing) div.formControl.infoContainer texta
|
|||||||
}
|
}
|
||||||
|
|
||||||
section#addPost form, section#editPost form {
|
section#addPost form, section#editPost form {
|
||||||
margin: auto 4rem;
|
margin: auto 4rem 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
form .formControl .ck.ck-editor__top .ck-sticky-panel .ck-toolbar {
|
form .formControl .ck.ck-editor__top .ck-sticky-panel .ck-toolbar {
|
||||||
@ -276,10 +276,6 @@ section#editPost table td, th {
|
|||||||
min-width: 10rem;
|
min-width: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
section#editPost form {
|
|
||||||
margin-bottom: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
section#newsletter form {
|
section#newsletter form {
|
||||||
margin: 0 5em;
|
margin: 0 5em;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user