Skip to content

Commit

Permalink
Merge pull request #2 from HoseaCodes/main
Browse files Browse the repository at this point in the history
Update Articles
  • Loading branch information
HoseaCodes authored Aug 1, 2023
2 parents e70b5bf + d2eb520 commit 94a7f52
Show file tree
Hide file tree
Showing 129 changed files with 8,405 additions and 1,752 deletions.
59 changes: 56 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Welcome, to my personal blog and portfolio. Sharing information is vital and esp

![Article Page](https://i.imgur.com/PeDkdtv.png)

## Getting Started

The user is brought to the home page where they can navigate to my [portfolio](www.dominiquehosea.com), my blog posts, my about me, or contact page. The home page is an introduction to who I am. The is a brief history of my experience with the option to download my resume. Additionally, I have the technologies that I am currently using, a project showcase, an embbed [Twitter](https://twitter.com/DominiqueRHosea) widget, and testimonies.

## Technologies Used

This application was developed with a full MERN stack. and written in JavaScript. Styling done with Bootstrap, Material UI, SASS or SCSS and CSS.
Expand All @@ -35,9 +39,22 @@ Dependencies used:
- Material UI - a library for building pre-styled components
- SASS - a preprocessor scripting language that is interpreted or compiled into Cascading Style Sheets

## Getting Started

The user is brought to the home page where they can navigate to my [portfolio](www.dominiquehosea.com), my blog posts, my about me, or contact page. The home page is an introduction to who I am. The is a brief history of my experience with the option to download my resume. Additionally, I have the technologies that I am currently using, a project showcase, an embbed [Twitter](https://twitter.com/DominiqueRHosea) widget, and testimonies.
## Features

✅ Own your content
✅ Write using Markdown On Github Issues
✅ Syntax/Code Highlighting
✅ Fully customizable
✅ Tags - Topics
✅ Links
✅ Reactions
✅ View Comments
✅ Images
✅ Minutes Read
✅ Beautiful UI Like Medium
✅ Easy deployment: Using Github Pages
✅ Instant Effects on Blog when changing github issues
✅ Beautiful blockquote

## Frontend

Expand Down Expand Up @@ -172,8 +189,37 @@ To execute tests:
npm test
```

## 3rd Party Packages

| Name | Use Case |
| ----------------------------------------------------- | ----------- |
| [AOS](https://www.markdownguide.org/extended-syntax/) | Animation |
| [Axios](https://www.npmjs.com/package/axios) | HTTP client |
| bcrypt | |
| dompurify | |
| framer-motion | |
| imagemin | |
| markdown | |
| marked | |
| moment | |
| morgan | |
| node-cache | |
| node-sass | |
| react-bootstrap | |
| react-bootstrap | |
| react-icons | |
| react-masonry-css | |
| react-sticky-state | |
| react-twitter-widgets | |
| reactjs-popup | |
| source-map-explorer | |
| styled-components | |
| winston | |

## External APIs

- [Paypal]()
- [cloudinary]()
- [Send Grid](https://app.sendgrid.com/)
- [Get Form](https://getform.io/)
- [Swagger API](https://support.smartbear.com/swaggerhub/docs/about.html)
Expand All @@ -186,3 +232,10 @@ npm test
- Routing for 404
- Add Calorie Kicthen, Sneaker-API, Ecommerce-Site, Ecommerce-Backend-Template, React-Crypto, Cypto-Learn, CareerConnect, and Expense-Tracker as project case studies.
- Confgiure multiple env
- Syntax/Code Highlighting
- Tags - Topics
- Reactions
- View Comments

- ~~Minutes Read~~
https://github.com/saadpasta/react-blog-github
198 changes: 176 additions & 22 deletions controllers/article.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Articles from '../models/article.js';
import Comments from '../models/article.js';
import Logger from '../utils/logger.js';
import {cache} from '../utils/cache.js';
import axios from 'axios'

const logger = new Logger('articles')

Expand All @@ -9,10 +12,24 @@ async function getArticle(req, res) {

logger.info("Returning the list of articles");

res.cookie('articles-cache', articles.length + "articles", {
maxAge: 1000 * 60 * 60, // would expire after an hour
httpOnly: true, // The cookie only accessible by the web server
})

cache.set( articles.length + "articles", {
status: 'success',
articles: articles,
result: articles.length,
location: 'cache',
});

res.json({
status: 'success',
articles: articles,
result: articles.length,
location: 'main',

})
} catch (err) {

Expand All @@ -25,28 +42,69 @@ async function getArticle(req, res) {
async function createArticle(req, res) {
try {

const { article_id, title, subtitle, markdown, description, images, category } = req.body;
const { article_id, title, subtitle, markdown, description, images, category, dev, medium } = req.body;

if (!images) {

logger.error("No image provided.");

return res.status(400).json({ msg: "No image upload" });
logger.error("No image provided.");
return res.status(400).json({ msg: "No image upload" });
}

const article = await Articles.find({ article_id });

if (article) {

logger.error("Article already exist.");
logger.error("Article already exist.");

return res.status(400).json({ msg: "This article already exists." })
return res.status(400).json({ msg: "This article already exists." })
}

const newArticle = new Articles({
article_id, title, subtitle, markdown, description, images, category
article_id, title, subtitle, markdown, description, images, category
})

try {
if (dev) {
await axios.post('https://dev.to/api/articles',
{
"article": {
"title": title,
"published": false,
"body_markdown": markdown,
"tags": ["api", "hoseacodes"],
"series": "Hello series"
}
}, {
headers: { "api-key": process.env.FOREMAPI },
}
)
logger.info('Published to Dev To')
}

if (medium) {
const userId = process.env.MEDIUMID
await axios.post(`https://api.medium.com/v1/users/${userId}/posts`,
{
"title": title,
"contentFormat": "markdown",
"content": markdown,
"canonicalUrl": images,
"tags": ["api", "hoseacodes"],
"publishStatus": "public",
"notifyFollowers": true
}, {
headers: { Authorization: `Bearer ${process.env.MEDIUMAPI}` },
}
)
logger.info('Published to Medium')
}

} catch (error) {
logger.error(`Error: ${error}`);
}


res.clearCookie('artilces-cache');
await newArticle.save()

logger.info(`New article ${title} has been created`);
Expand All @@ -66,7 +124,7 @@ async function deleteArticle(req, res) {
logger.info(`Deleted article ${req.params.id} has been deleted`);

await Articles.findByIdAndDelete(req.params.id)

res.clearCookie('articles-cache');
res.json({ msg: "Deleted a article" })
} catch (err) {

Expand All @@ -76,28 +134,60 @@ async function deleteArticle(req, res) {
}
}

async function updateArticle(req, res) {
try {
const { title, subtitle, description, content, images, category } = req.body;

if (!images) {
async function deletePostcomment(req, res) {
try {
const post_id = req.body.post_id

logger.error("No image provided.");
logger.info(`Deleted comment ${req.params.id} has been deleted`);

return res.status(400).json({ msg: "No image upload" })
}
await Articles.findByIdAndDelete(req.params.id)
res.clearCookie('comments-cache');
res.json({ msg: "Deleted a article" })
} catch (err) {

logger.error(err)

return res.status(500).json({ msg: err.message })
}
}

async function updateLikes(req, res) {
try {

const uid = req.body.uid
const post_id = req.params.id
const { likes } = req.body;

const values = [ uid, post_id ]
console.log(values)
likes += 1;
await Articles.findOneAndUpdate({ _id: req.params.id },
{likes});

} catch (err) {

logger.error(err);

return res.status(500).json({ msg: err.message });
}
}

async function updateArticleComment(req, res) {
try {
const { article_id, post_id, comment, markdown, user_id, date_created } = req.body;

const originalBody = req.body

await Articles.findOneAndUpdate({ _id: req.params.id }, {
title: title.toLowerCase(), subtitle, description, content, images, category
await Comments.findOneAndUpdate({ _id: req.params.id }, {
article_id, post_id, comment, user_id, markdown, date_created
})

const preparedLog = `Changing the following: ${originalBody} to ${req.body} for the article ${title}`;

const preparedLog = `Changing the following: ${originalBody} to ${req.body} for the comment ${title}`;
res.clearCookie('comments-cache');
logger.info(preparedLog);

res.json({ msg: 'Updated a article' })
res.json({ msg: 'Updated a comment' })
} catch (err) {

logger.error(err);
Expand All @@ -106,6 +196,37 @@ async function updateArticle(req, res) {
}
}

async function updateArticle(req, res) {
try {
const { title, subtitle, description, content, images, category } = req.body;
res.clearCookie('articles-cache');

if (!images) {

logger.error("No image provided.");
res.clearCookie('user-cache');
return res.status(400).json({ msg: "No image upload" })
}

const originalBody = req.body

await Articles.findOneAndUpdate({ _id: req.params.id }, {
title: title.toLowerCase(), subtitle, description, content, images, category
})

const preparedLog = `Changing the following: ${originalBody} to ${req.body} for the article ${title}`;

logger.info(preparedLog);

res.json({ msg: 'Updated a article' })
} catch (err) {

logger.error(err);

return res.status(500).json({ msg: err.message });
}
}

async function archiveArticle(req, res) {
try {
const { archive } = req.body;
Expand All @@ -130,8 +251,41 @@ async function archiveArticle(req, res) {
}
}

export { getArticle,
async function createArticleComment(req, res) {
try {

const { article_id, post_id, comment, markdown, user_id, date_created } = req.body;

const article = await Articles.findOne({ article_id });

const newComment = new Comments({
article_id, post_id, comment, user_id, markdown, date_created
})

await newComment.save()

logger.info(`New comment has been created`);
res.clearCookie('comments-cache');

res.json({ msg: "Created a new comment" });
} catch (err) {

logger.error(err)

return res.status(500).json({ msg: err.message })
}
}



export {
getArticle,
createArticle,
createArticleComment,
archiveArticle,
deleteArticle,
updateArticle };
deletePostcomment,
updateArticle,
updateArticleComment,
updateLikes,
};
Loading

0 comments on commit 94a7f52

Please sign in to comment.