Skip to content

Commit

Permalink
Merge pull request #29 from andela/ft-like-dislike-article-167484597
Browse files Browse the repository at this point in the history
#167484597 implemented like or dislike an article
  • Loading branch information
mkiterian committed Aug 22, 2019
2 parents 1caca54 + 2a08e1a commit 642a12c
Show file tree
Hide file tree
Showing 10 changed files with 497 additions and 6 deletions.
266 changes: 264 additions & 2 deletions src/controllers/articleController.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { User, Article } from '../sequelize/models';
/* eslint-disable no-shadow */
/* eslint-disable max-len */
import { User, Article, Reaction } from '../sequelize/models';
import { slugGen, uploadImage } from '../helpers/articles/articleHelper';

/**
Expand Down Expand Up @@ -35,7 +37,7 @@ class ArticleController {
payload.authorId = id;
const article = await Article.create(payload);
const {
slug, category, images, tagList, authorId
slug, category, images, tagList, authorId,
} = article;
if (article) {
return res.status(201).json({
Expand Down Expand Up @@ -92,6 +94,266 @@ class ArticleController {
throw (err);
}
}

/**
* @description like an article
* @param {object} req
* @param {object} res
* @return {object} return object with a liked article
*/
static async likeArticle(req, res) {
try {
const liker = req.userData.id;
const slugId = req.params.articleSlug;
const likeVote = 1;
const dislikeVote = 0;

const findArticle = await Article.findOne({ where: { slug: slugId } });

if (!findArticle) {
return res.status(404).json({
message: 'Article not found'
});
}

const reactedAlready = await Reaction.findOne({ where: { articleSlug: slugId, userId: liker } });

const { id } = findArticle;

if (!reactedAlready) {
const likedArticle = await Reaction.create({
articleId: id,
articleSlug: slugId,
userId: liker,
likes: likeVote,
});

const {
articleSlug, userId, likes
} = likedArticle;

if (likedArticle) {
await Article.increment({ likes: 1 }, { where: { slug: slugId } });

return res.status(200).json({
message: 'You have liked the article',
reaction: {
articleSlug,
userId,
likes
}
});
}
}

const { likes } = reactedAlready;

if (likes > 0) {
if (reactedAlready) {
const removeLike = await Reaction.update({ likes: dislikeVote }, { where: { articleSlug: slugId, userId: liker } });

if (removeLike) {
await Article.decrement({ likes: 1 }, { where: { slug: slugId } });
const updatedArticle = await Reaction.findOne({ where: { articleSlug: slugId, userId: liker } });

const {
articleSlug, userId, likes,
} = updatedArticle;

return res.status(200).json({
message: 'You have removed your like',
reaction: {
articleSlug,
userId,
likes,
}
});
}
}
} else {
const { dislikes } = reactedAlready;

if (dislikes > 0) {
const removeDislike = await Reaction.update({ dislikes: dislikeVote }, { where: { articleSlug: slugId, userId: liker } });

if (removeDislike) {
await Article.decrement({ dislikes: 1 }, { where: { slug: slugId } });
const likeArticleAgain = await Reaction.update({ likes: likeVote }, { where: { articleSlug: slugId, userId: liker } });

if (likeArticleAgain) {
await Article.increment({ likes: 1 }, { where: { slug: slugId } });
const updatedArticle = await Reaction.findOne({ where: { articleSlug: slugId, userId: liker } });

const {
articleSlug, userId, likes,
} = updatedArticle;

return res.status(200).json({
message: 'You have liked the article',
reaction: {
articleSlug,
userId,
likes,
}
});
}
}
} else {
const likeArticleAgain = await Reaction.update({ likes: likeVote }, { where: { articleSlug: slugId, userId: liker } });
await Article.increment({ likes: 1 }, { where: { slug: slugId } });

if (likeArticleAgain) {
const updatedArticle = await Reaction.findOne({ where: { articleSlug: slugId, userId: liker } });

const {
articleSlug, userId, likes,
} = updatedArticle;

return res.status(200).json({
message: 'You have liked the article',
reaction: {
articleSlug,
userId,
likes,
}
});
}
}
}
} catch (err) {
throw (err);
}
}

/**
* @description dislike an article
* @param {object} req
* @param {object} res
* @return {object} return object with a disliked article
*/
static async dislikeArticle(req, res) {
try {
const disliker = req.userData.id;
const slugId = req.params.articleSlug;
const likeVote = 1;
const dislikeVote = 0;

const findArticle = await Article.findOne({ where: { slug: slugId } });

if (!findArticle) {
return res.status(404).json({
message: 'Article not found'
});
}

const reactedAlready = await Reaction.findOne({ where: { articleSlug: slugId, userId: disliker } });

const { id } = findArticle;

if (!reactedAlready) {
const dislikedArticle = await Reaction.create({
articleId: id,
articleSlug: slugId,
userId: disliker,
dislikes: likeVote,
});
const {
articleSlug, userId, dislikes
} = dislikedArticle;

if (dislikedArticle) {
await Article.increment({ dislikes: 1 }, { where: { slug: slugId } });

return res.status(200).json({
message: 'You have disliked the article',
reaction: {
articleSlug,
userId,
dislikes
}
});
}
}

const { dislikes } = reactedAlready;

if (dislikes > 0) {
if (reactedAlready) {
const removeDislike = await Reaction.update({ dislikes: dislikeVote }, { where: { articleSlug: slugId, userId: disliker } });

if (removeDislike) {
const updatedArticle = await Reaction.findOne({ where: { articleSlug: slugId, userId: disliker } });
await Article.decrement({ dislikes: 1 }, { where: { slug: slugId } });

const {
articleSlug, userId, dislikes,
} = updatedArticle;

return res.status(200).json({
message: 'You have removed your dislike',
reaction: {
articleSlug,
userId,
dislikes,
}
});
}
}
} else {
const { likes } = reactedAlready;

if (likes > 0) {
const removeLike = await Reaction.update({ likes: dislikeVote }, { where: { articleSlug: slugId, userId: disliker } });

if (removeLike) {
await Article.decrement({ likes: 1 }, { where: { slug: slugId } });
const dislikeArticleAgain = await Reaction.update({ dislikes: likeVote }, { where: { articleSlug: slugId, userId: disliker } });

if (dislikeArticleAgain) {
await Article.increment({ dislikes: 1 }, { where: { slug: slugId } });
const updatedArticle = await Reaction.findOne({ where: { articleSlug: slugId, userId: disliker } });

const {
articleSlug, userId, dislikes,
} = updatedArticle;

return res.status(200).json({
message: 'You have disliked the article',
reaction: {
articleSlug,
userId,
dislikes,
}
});
}
}
} else {
const dislikeArticleAgain = await Reaction.update({ dislikes: likeVote }, { where: { articleSlug: slugId, userId: disliker } });

if (dislikeArticleAgain) {
await Article.increment({ dislikes: 1 }, { where: { slug: slugId } });
const updatedArticle = await Reaction.findOne({ where: { articleSlug: slugId, userId: disliker } });

const {
articleSlug, userId, dislikes,
} = updatedArticle;

return res.status(200).json({
message: 'You have disliked the article',
reaction: {
articleSlug,
userId,
dislikes,
}
});
}
}
}
} catch (err) {
throw (err);
}
}
}


export default ArticleController;
5 changes: 3 additions & 2 deletions src/controllers/userController.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,10 @@ class Authentication {
username: req.user.userName,
email: req.user.email
}
});
});
}
/**

/**
* @description user logout
* @param {object} req
* @param {object} res
Expand Down
2 changes: 2 additions & 0 deletions src/routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ router.post('/api/v1/users/logout', [verifyToken], UserAuth.logout);
router.post('/api/v1/users/login', Validation.loginValidation, UserAuth.login);
router.post('/api/v1/articles', [verifyToken, connectMulti, Validation.createArticleValidation, ContentType, Validation.imageValidation], Article.createArticle);
router.get('/api/v1/articles', Article.getAllArticles);
router.put('/api/v1/articles/:articleSlug/like', verifyToken, Article.likeArticle);
router.put('/api/v1/articles/:articleSlug/dislike', verifyToken, Article.dislikeArticle);
router.post('/api/v1/profiles/:userName/follow', verifyToken, UserFollow.followUser);
router.delete('/api/v1/profiles/:userName/unfollow', verifyToken, UserFollow.unFollowUser);
router.get('/api/v1/profiles/:userName/following', verifyToken, UserFollow.getFollowingList);
Expand Down
35 changes: 35 additions & 0 deletions src/sequelize/migrations/20190820190355-create-reaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export default {
up: (queryInterface, Sequelize) => queryInterface.createTable('Reactions', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
articleId: {
allowNull: false,
type: Sequelize.INTEGER
},
articleSlug: {
type: Sequelize.STRING
},
userId: {
type: Sequelize.INTEGER
},
likes: {
type: Sequelize.INTEGER
},
dislikes: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}),
down: queryInterface => queryInterface.dropTable('Reactions')
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export default {
up(queryInterface, Sequelize) {
return Promise.all([
queryInterface.addColumn('Articles', 'likes', {
type: Sequelize.INTEGER,
defaultValue: 0
}),

queryInterface.addColumn('Articles', 'dislikes', {
type: Sequelize.INTEGER,
defaultValue: 0
}),
]);
},

down(queryInterface) {
return Promise.all([
queryInterface.removeColumn(
'Articles',
'likes'
),
queryInterface.removeColumn(
'Articles',
'dislikes'
)
]);
}
};
1 change: 1 addition & 0 deletions src/sequelize/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export default (sequelize, DataTypes) => {
User.hasMany(models.Follow, { foreignKey: 'following', onDelete: 'CASCADE' });
User.hasMany(models.Follow, { foreignKey: 'follower', onDelete: 'CASCADE' });
User.hasMany(models.Article, { foreignKey: 'authorId', as: 'author', onDelete: 'CASCADE' });
User.hasMany(models.Reaction, { foreignKey: 'userId', as: 'LikerOrDisliker', onDelete: 'CASCADE' });
User.hasMany(models.Notification, { foreignKey: 'userId', onDelete: 'CASCADE' });
};
return User;
Expand Down
Loading

0 comments on commit 642a12c

Please sign in to comment.