Fixed some bugs in the newsletter images, made some minor improvements in other areas. Added in unsubscribe functionality
🚀 Deploy website on push / 🎉 Deploy (push) Successful in 21s
🚀 Deploy website on push / 🎉 Deploy (push) Successful in 21s
Signed-off-by: rodude123 <rodude123@gmail.com>
This commit is contained in:
+21
-12
@@ -296,17 +296,18 @@ class blogData
|
||||
$latest = $this->getLatestBlogPost();
|
||||
$prevTitle = $latest["title"];
|
||||
$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)
|
||||
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :abstract, :body, :bodyText, :categories, :keywords, :folderID);");
|
||||
$stmt->bindParam(":title", $title);
|
||||
$stmt->bindParam(":dateCreated", $dateCreated);
|
||||
$stmt->bindParam(":dateModified", $dateCreated);
|
||||
$isFeatured = $featured ? 1 : 0;
|
||||
$stmt->bindParam(":featured", $isFeatured);
|
||||
// $isFeatured = $featured ? 1 : 0;
|
||||
$stmt->bindParam(":featured", $featured);
|
||||
$stmt->bindParam(":headerImg", $headerImage);
|
||||
$stmt->bindParam(":abstract", $abstract);
|
||||
$stmt->bindParam(":body", $newBody);
|
||||
@@ -323,6 +324,8 @@ class blogData
|
||||
$stmtEmails = $conn->prepare("SELECT email FROM newsletter;");
|
||||
$stmtEmails->execute();
|
||||
$emails = $stmtEmails->fetchAll(PDO::FETCH_ASSOC);
|
||||
$headerImage = substr($headerImage, 10);
|
||||
$headerImage = str_ireplace("%2F", "/", $headerImage);
|
||||
|
||||
$emailBody = <<<EOD
|
||||
<!DOCTYPE html>
|
||||
@@ -533,7 +536,7 @@ class blogData
|
||||
<div class="postContainer">
|
||||
<h2>latest post</h2>
|
||||
<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 class="post">
|
||||
@@ -546,7 +549,7 @@ class blogData
|
||||
<div class="postContainer">
|
||||
<h2>in case you missed the previous post</h2>
|
||||
<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 class="post">
|
||||
@@ -556,21 +559,26 @@ class blogData
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
EOD;
|
||||
|
||||
foreach ($emails as $email)
|
||||
{
|
||||
$emailFooter = <<<EOD
|
||||
<footer>
|
||||
<div class="nav">
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="date">2023</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
EOD;
|
||||
EOD;
|
||||
$emailBody .= $emailFooter;
|
||||
|
||||
foreach ($emails as $email)
|
||||
{
|
||||
$this->sendMail($email["email"], $emailBody, "Hey, Rohit's blog has a new post!");
|
||||
}
|
||||
|
||||
@@ -642,7 +650,8 @@ EOD;
|
||||
unlink($result["headerImg"]);
|
||||
$stmt = $conn->prepare("UPDATE blog SET headerImg = :headerImg WHERE ID = :ID;");
|
||||
$stmt->bindParam(":ID", $ID);
|
||||
$stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
|
||||
$location = urldecode("../" . $targetFile["imgLocation"]);
|
||||
$stmt->bindParam(":headerImg", $location);
|
||||
$stmt->execute();
|
||||
if ($stmt->rowCount() > 0)
|
||||
{
|
||||
@@ -1168,7 +1177,7 @@ EOD;
|
||||
<div class="nav">
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
<div class="date">2023</div>
|
||||
|
||||
@@ -282,17 +282,18 @@ class blogRoutes implements routesInterface
|
||||
if ($message === "email not found")
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
if ($message === "error")
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
$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;
|
||||
});
|
||||
|
||||
@@ -324,8 +325,8 @@ class blogRoutes implements routesInterface
|
||||
$headerImg = null;
|
||||
}
|
||||
|
||||
$featured = $data["featured"] === "true";
|
||||
$insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], $featured, $data["categories"], $headerImg);
|
||||
// $featured = $data["featured"] === "true";
|
||||
$insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], intval($data["featured"]), $data["categories"], $headerImg);
|
||||
if (!is_int($insertedID))
|
||||
{
|
||||
// uh oh something went wrong
|
||||
|
||||
@@ -79,7 +79,7 @@ article a {
|
||||
|
||||
article a::before,
|
||||
article a::after {
|
||||
visibility: hidden;
|
||||
visibility: visible;
|
||||
position: absolute;
|
||||
margin-top: 1px;
|
||||
}
|
||||
@@ -93,9 +93,9 @@ article a::after {
|
||||
content: '>';
|
||||
}
|
||||
|
||||
article a:hover::before,
|
||||
article a:hover::after {
|
||||
visibility: visible;
|
||||
article a:hover,
|
||||
article a:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
article h1 {
|
||||
@@ -106,6 +106,10 @@ article h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
article h3:not(div.byLine > h3), .otherPosts h3 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
aside.sideContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -108,14 +108,18 @@ section.largePost .outerContent .postContent a {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
#main .errorFof {
|
||||
#main .errorFof, #main .unsubscribe {
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fof {
|
||||
#main .unsubscribe {
|
||||
height: 50dvh;
|
||||
}
|
||||
|
||||
.centered {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@
|
||||
</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>
|
||||
|
||||
+45
-10
@@ -38,7 +38,7 @@ function goToURL(url)
|
||||
document.querySelector('#cookiePopup').classList.add('hidden');
|
||||
}
|
||||
|
||||
if (url === '/blog/' || url === '/blog')
|
||||
if (url === '/blog' || url === 'blog')
|
||||
{
|
||||
loadHomeContent();
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -136,7 +145,7 @@ function submitNewsletter()
|
||||
{
|
||||
document.querySelector('#newsletterMessage').classList.add('error');
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* @param {string} dateString - the date string
|
||||
@@ -175,7 +209,7 @@ function createLargePost(post)
|
||||
outerContent.classList.add('outerContent');
|
||||
let img = document.createElement('img');
|
||||
img.className = 'banner';
|
||||
img.src = post.headerImg;
|
||||
img.src = post.headerImg.replaceAll('%2F', '/');
|
||||
img.alt = post.title;
|
||||
outerContent.appendChild(img);
|
||||
let content = document.createElement('div');
|
||||
@@ -464,7 +498,7 @@ function createMetaTag(nameOrProperty, attribute, value)
|
||||
*/
|
||||
function insertMetaTags(json)
|
||||
{
|
||||
let metaDesc = document.querySelector('meta[name="description"]');
|
||||
let metaDesc = document.querySelector('meta[name=\'description\']');
|
||||
metaDesc.setAttribute('content', json.abstract);
|
||||
|
||||
// Twitter meta tags
|
||||
@@ -478,11 +512,11 @@ function insertMetaTags(json)
|
||||
createMetaTag('og:image', 'content', json.headerImg);
|
||||
createMetaTag('og:url', 'content', window.location.href);
|
||||
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');
|
||||
|
||||
//Keywords
|
||||
let metKeywords = document.querySelector('meta[name="keywords"]');
|
||||
let metKeywords = document.querySelector('meta[name=\'keywords\']');
|
||||
let keywords = metKeywords.getAttribute('content');
|
||||
keywords += `, ${json.keywords}`;
|
||||
metKeywords.setAttribute('content', keywords);
|
||||
@@ -515,6 +549,7 @@ async function loadIndividualPost(title)
|
||||
let mainContent = document.createElement('div');
|
||||
mainContent.classList.add('mainContent');
|
||||
let article = document.createElement('article');
|
||||
let headerImg = json.headerImg.replaceAll('%2F', '/');
|
||||
article.innerHTML = `
|
||||
<h1>${json.title}</h1>
|
||||
<div class="byLine">
|
||||
@@ -522,9 +557,9 @@ async function loadIndividualPost(title)
|
||||
<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}"
|
||||
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 class="cover" style="background-image: url('${json.headerImg}')"></div>
|
||||
<div class="cover" style="background-image: url('${headerImg}')"></div>
|
||||
${json.body}
|
||||
`;
|
||||
let comments = document.createElement('section');
|
||||
@@ -662,7 +697,7 @@ function loadPrivacyPolicy()
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>Last Updated: Nov 12, 2023</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>
|
||||
<br>
|
||||
|
||||
@@ -833,7 +868,7 @@ function show404()
|
||||
{
|
||||
document.querySelector('#main').innerHTML = `
|
||||
<div class="errorFof">
|
||||
<div class="fof">
|
||||
<div class="centered">
|
||||
<h1>Blog post, Category or page not found</h1>
|
||||
<a href="/blog/" class="btn btnPrimary">See all blog posts</a>
|
||||
</div>
|
||||
|
||||
@@ -334,11 +334,18 @@ a.link {
|
||||
|
||||
a.link::before,
|
||||
a.link::after {
|
||||
visibility: hidden;
|
||||
visibility: visible;
|
||||
position: absolute;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
nav a.link::before,
|
||||
nav a.link::after,
|
||||
.nav a.link::before,
|
||||
.nav a.link::after {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a.link::before {
|
||||
content: ' <';
|
||||
margin-left: -0.5em;
|
||||
@@ -348,11 +355,21 @@ a.link::after {
|
||||
content: '> ';
|
||||
}
|
||||
|
||||
a.link:hover::before,
|
||||
a.link:hover::after {
|
||||
a.link:hover {
|
||||
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;
|
||||
}
|
||||
|
||||
nav a.link:hover, .nav a.link:hover {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.error, div.success {
|
||||
color: #FFFFFF;
|
||||
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 {
|
||||
margin: auto 4rem;
|
||||
margin: auto 4rem 4rem;
|
||||
}
|
||||
|
||||
form .formControl .ck.ck-editor__top .ck-sticky-panel .ck-toolbar {
|
||||
@@ -276,10 +276,6 @@ section#editPost table td, th {
|
||||
min-width: 10rem;
|
||||
}
|
||||
|
||||
section#editPost form {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
section#newsletter form {
|
||||
margin: 0 5em;
|
||||
}
|
||||
Reference in New Issue
Block a user