Skip to content

Commit

Permalink
Merge 77d4a48 into d6dad38
Browse files Browse the repository at this point in the history
  • Loading branch information
olajide1234 authored Mar 20, 2019
2 parents d6dad38 + 77d4a48 commit 80d12fd
Show file tree
Hide file tree
Showing 15 changed files with 392 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Authors Haven - A Social platform for the creative at heart.

[![Build Status](https://travis-ci.com/andela/vidar-ah-backend.svg?branch=develop)](https://travis-ci.com/andela/vidar-ah-backend) [![Coverage Status](https://coveralls.io/repos/github/andela/vidar-ah-backend/badge.svg?branch=ft-create-user-article-%23164139686)](https://coveralls.io/github/andela/vidar-ah-backend?branch=ft-create-user-article-%23164139686) [![](https://img.shields.io/badge/Protected_by-Hound-a873d1.svg)](https://houndci.com)
[![Build Status](https://travis-ci.com/andela/vidar-ah-backend.svg?branch=develop)](https://travis-ci.com/andela/vidar-ah-backend) [![Coverage Status](https://coveralls.io/repos/github/andela/vidar-ah-backend/badge.svg?branch=develop)](https://coveralls.io/github/andela/vidar-ah-backend?branch=ft-create-user-article-%23164139686) [![](https://img.shields.io/badge/Protected_by-Hound-a873d1.svg)](https://houndci.com)
=======

## Vision
Expand Down
55 changes: 54 additions & 1 deletion controllers/comment.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Comment, User } from '../models';
import Sequelize from 'sequelize';
import { Comment, User, CommentLikes } from '../models';
import isCommentLikedByUser from '../helpers/isCommentLikedByUser';

/**
* @class CommentController
Expand Down Expand Up @@ -58,10 +60,19 @@ export default class CommentController {
where: {
articleSlug
},
group: ['User.username', 'User.bio', 'User.email', 'Comment.id'],
include: [
{
model: User,
attributes: ['username', 'bio', 'email']
},
{
model: CommentLikes,
attributes: [
[
Sequelize.fn('COUNT', Sequelize.col('CommentLikes.commentId')), 'commentCount'
]
]
}
]
});
Expand Down Expand Up @@ -152,4 +163,46 @@ export default class CommentController {
});
}
}

/**
* @description - Like/unlike an article comment
* @static
*
* @param {object} req - HTTP Request
* @param {object} res - HTTP Response
*
* @memberof CommentController
*
* @returns {string} Like/unlike comment result
*/
static async likeComment(req, res) {
const { id } = req.params;
const { id: userId } = req.user;
try {
// Delete comment like, if already liked by user
if (await isCommentLikedByUser(id, userId)) {
await CommentLikes.destroy({
where: {
userId, commentId: id
}
});
return res.status(201).json({
success: true,
message: 'Comment unliked successfully',
});
}
await CommentLikes.create({
userId, commentId: id
});
return res.status(201).json({
success: true,
message: 'Comment liked successfully',
});
} catch (error) {
return res.status(500).json({
success: false,
errors: [error.message]
});
}
}
}
40 changes: 39 additions & 1 deletion doc.json
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,45 @@
}
}
}

},
"/comments{id}/like": {
"put": {
"tags": [
"CommentLike"
],
"summary": "Like a comment article",
"description": "",
"operationId": "Like comment",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "authorization",
"in": "header",
"description": "A token to verify the user",
"required": true,
"type": "string"
},
{
"in": "header",
"name": "id",
"description": "Id of comment to like",
"required": true
}
],
"responses": {
"201": {
"description": "Article liked/unliked successfully"
},
"404": {
"description": "Comment not found"
}
}
}
}
},
"/articles/{slug}/comments": {
Expand Down
19 changes: 19 additions & 0 deletions helpers/isCommentLikedByUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { CommentLikes } from '../models';

/**
* @description This function checks if a function has been liked by a user
* @param {string} commentId Comment ID
* @param {string} userId User id
* @returns {boolean} if comment has been liked
*/
const isCommentLikedByUser = async (commentId, userId) => {
const findComment = await CommentLikes.findOne({
where: {
userId, commentId
}
});
if (findComment) { return true; }
return false;
};

export default isCommentLikedByUser;
24 changes: 24 additions & 0 deletions middleware/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,30 @@ export const validateCommentUser = async (req, res, next) => {
});
}
};
export const validateCommentExist = async (req, res, next) => {
const {
params: { id }
} = req;
try {
const comment = await Comment.findOne({
where: {
id
}
});
if (!comment) {
return res.status(404).json({
success: false,
errors: ['Comment not found.']
});
}
return next();
} catch (error) {
return res.status(500).json({
success: false,
error: [error.message]
});
}
};

export const validateArticleExist = async (req, res, next) => {
const { slug } = req.params;
Expand Down
26 changes: 26 additions & 0 deletions migrations/20190318175823-create-comment-likes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.createTable('CommentLikes', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
commentId: {
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}),

down: queryInterface => queryInterface.dropTable('CommentLikes'),
};
4 changes: 4 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ module.exports = (sequelize, DataTypes) => {
foreignKey: 'userId',
onDelete: 'CASCADE'
});
User.hasMany(models.CommentLikes, {
foreignKey: 'userId',
onDelete: 'CASCADE'
});
};


Expand Down
4 changes: 4 additions & 0 deletions models/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ module.exports = (sequelize, DataTypes) => {
foreignKey: 'userId',
onDelete: 'CASCADE',
});
Comment.hasMany(models.CommentLikes, {
foreignKey: 'commentId',
onDelete: 'CASCADE'
});
};
return Comment;
};
17 changes: 17 additions & 0 deletions models/commentlikes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = (sequelize, DataTypes) => {
const CommentLikes = sequelize.define('CommentLikes', {
commentId: DataTypes.INTEGER,
userId: DataTypes.INTEGER
}, {});
CommentLikes.associate = (models) => {
CommentLikes.belongsTo(models.Comment, {
foreignKey: 'commentId',
onDelete: 'CASCADE'
});
CommentLikes.belongsTo(models.User, {
foreignKey: 'userId',
onDelete: 'CASCADE'
});
};
return CommentLikes;
};
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion routes/v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import {
validateEditComment,
validateCommentUser,
validateArticleExist,
returnValidationErrors
validateCommentExist,
returnValidationErrors,
} from '../middleware/validation';
import FollowController from '../controllers/follow';
import followVerification from '../middleware/follow';
Expand Down Expand Up @@ -194,5 +195,12 @@ apiRoutes.route('/articles/:slug/comments/:id')
CommentController.deleteComment
);

apiRoutes.route('/comments/:id/like')
.put(
Auth.verifyUser,
isUserVerified,
validateCommentExist,
CommentController.likeComment
);

export default apiRoutes;
7 changes: 7 additions & 0 deletions test/helpers/articleDummyData.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ export const article2 = {
description: 'An article can be updated',
body: 'Update an article if you are the owner of the article.'
};

export const article3 = {
title: 'This is the title of another test third article',
description: 'This is the description of another third test article',
body:
'Lorem ipsum dolor sit amet, third consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
};
16 changes: 15 additions & 1 deletion test/helpers/userDummyData.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,32 @@ export const validUser = {

export const validCommentUser = {
username: 'MuhammaduBuhari',
email: 'ayinlaolajide@gmail.com',
email: 'ayinlaolajide099@gmail.com',
name: 'Muhammadu Buhari',
password: '1234567'
};

export const validLikeCommentUser = {
username: 'FelaAnikulapo',
email: 'felasssss@gmail.com',
name: 'Fela Kuti',
password: '1234567'
};

export const wrongCommentUser = {
username: 'AishaBuhari',
email: 'ayinlaolajide2345@gmail.com',
name: 'Aisha Buhari',
password: '1234567'
};

export const wrongLikeCommentUser = {
username: 'JohnDoe',
email: 'johndoe2345@gmail.com',
name: 'John Doe',
password: '1234567'
};

export const validUser1 = {
username: 'flippin',
email: 'flipping2234@gmail.com',
Expand Down
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ import './updateVerifiedStatusHelper.spec';
import './resetpassword.spec';
import './category.spec';
import './follow.spec';
import './likeComment.spec';
Loading

0 comments on commit 80d12fd

Please sign in to comment.