Skip to content

Commit

Permalink
Merge 44a401a into bf789fb
Browse files Browse the repository at this point in the history
  • Loading branch information
tunedev committed Jul 21, 2019
2 parents bf789fb + 44a401a commit fd2fcdd
Show file tree
Hide file tree
Showing 17 changed files with 609 additions and 540 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ node_modules

# package-lock.json file
package-lock.json

.vscode
2 changes: 1 addition & 1 deletion mail.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,4 @@ module.exports = {
ethereal: {
driver: 'ethereal'
}
}
};
34 changes: 32 additions & 2 deletions src/controllers/article.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
updateArticleService,
deleteArticleService,
articleRatingsService,
fetchRatingsService
fetchRatingsService,
likeCommentService
} from '../services/article.service';

import Helper from '../services/helper';
Expand Down Expand Up @@ -381,7 +382,36 @@ export default {
if (result === `Article with id: ${articleId} does not exist`) {
return Helper.failResponse(response, 404, result);
}

return Helper.successResponse(response, 200, result);
},

/**
* @method likeComment
* @description handles the logic to like a comment
* Route: POST: /articles/ratings
* @param {object} request containing the user request metadata
* @param {object} response contains the response to the question
*
* @returns {object} contains the appropriate response
*/

async likeComment(request, response) {
const { id } = request.user;
const { slug, commentId } = request.params;

const result = await likeCommentService(slug, commentId, id);

if (result === `The article with the specified slug does not exist`) {
return Helper.failResponse(response, 404, {
message: result
});
}

if (result === `The comment with the specified id does not exist`) {
return Helper.failResponse(response, 404, {
message: result
});
}
if (result) return Helper.successResponse(response, 200, result);
}
};
45 changes: 45 additions & 0 deletions src/db/migrations/20190712173952-create-comment-reaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('CommentReactions', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
userId: {
type: Sequelize.INTEGER,
allowNull: {
args: false,
references: {
models: 'Users',
key: 'id',
as: 'liker'
}
}
},
commentId: {
type: Sequelize.INTEGER,
allowNull: {
args: false,
references: {
models: 'Comments',
key: 'id',
as: 'liked'
}
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: queryInterface => {
return queryInterface.dropTable('CommentReactions');
}
};
9 changes: 0 additions & 9 deletions src/db/models/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,6 @@ export default (sequelize, DataTypes) => {
suffixSource: ['hash']
});

Article.associate = models => {
// associations can be defined here
Article.belongsTo(models.User, {
foreignKey: 'userId',
as: 'author',
onDelete: 'CASCADE'
});
};

Article.associate = models => {
// associations can be defined here
Article.belongsTo(models.User, {
Expand Down
2 changes: 1 addition & 1 deletion src/db/models/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default (sequelize, DataTypes) => {
slug: {
type: DataTypes.STRING,
allowNull: false,
unique: true
unique: false
},
highlightedText: {
type: DataTypes.TEXT,
Expand Down
39 changes: 39 additions & 0 deletions src/db/models/commentReaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module.exports = (sequelize, DataTypes) => {
const CommentReaction = sequelize.define('CommentReaction', {
userId: {
type: DataTypes.INTEGER,
allowNull: {
args: false,
references: {
model: 'Users',
key: 'id',
as: 'liker'
}
}
},
commentId: {
type: DataTypes.INTEGER,
allowNull: {
args: false,
references: {
model: 'Comments',
key: 'id',
as: 'liked'
}
}
}
});
CommentReaction.associate = models => {
// associations can be defined here
CommentReaction.belongsTo(models.User, {
foreignKey: 'userId',
as: 'liker'
});

CommentReaction.belongsTo(models.Comment, {
foreignKey: 'commentId',
as: 'liked'
});
};
return CommentReaction;
};
2 changes: 1 addition & 1 deletion src/db/models/rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = (sequelize, DataTypes) => {
},
rating: {
type: DataTypes.INTEGER,
allowNull: { args: false }
allowNull: false
}
});
Rating.associate = models => {
Expand Down
17 changes: 12 additions & 5 deletions src/routes/v1/article.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import commentsCheck from '../../middlewares/commentsCheck.middleware';
import reportController from '../../controllers/report.controller';

const { validator, checkValidationResult } = articleValidator;
const { verifyToken, adminCheck } = authorization;

const {
validator: paginationValidator,
Expand All @@ -28,15 +29,14 @@ const {
userGetAllPublishedArticles,
unPublishArticle,
getUserPublishedArticles,
userGetAllDraftArticles
userGetAllDraftArticles,
likeComment
} = articleController;

const { getCommentHistory, editComment, getSingleComment } = commentController;

const { editCommentCheck, getArticlesCommentsCheck } = commentsCheck;

const { verifyToken, adminCheck } = authorization;

const { createReport, removeArticle } = reportController;

const router = express.Router();
Expand Down Expand Up @@ -72,7 +72,7 @@ router
.delete('/:slug', verifyToken, deleteArticle)
.post(
'/ratings',
authorization.verifyToken,
verifyToken,
validator('rating'),
checkValidationResult,
articleController.ratings
Expand All @@ -87,7 +87,7 @@ router
)
.get(
'/:articleId/ratings',
authorization.verifyToken,
verifyToken,
validator('fetchRating'),
checkValidationResult,
articleController.fetchRatings
Expand All @@ -105,6 +105,13 @@ router
adminCheck,
checkValidationResult,
removeArticle
)
.get(
'/:slug/comments/:commentId/reactions',
verifyToken,
validator('commentLike'),
checkValidationResult,
likeComment
);

router.get(
Expand Down
78 changes: 76 additions & 2 deletions src/services/article.service.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import fs from 'fs';
import moment from 'moment';
import { upload } from '../helpers/image.helper';
import model from '../db/models';
import Helper from './helper';
import { paginationQueryMetadata, pageMetadata } from '../helpers/pagination';

const { Comment, Article, User, Follow, Rating } = model;
const { Comment, Article, User, Follow, Rating, CommentReaction } = model;
/** Istanbul ignore next */
/**
* @method createArticleService
Expand Down Expand Up @@ -558,6 +557,81 @@ export const articleRatingsService = async (articleId, rating, userId) => {
}
};

export const getCommentLikesCount = async commentId => {
const likeCount = await CommentReaction.findAndCountAll({
where: { commentId }
});

return likeCount.count;
};
/**
* @method likeCommentService
* - helps populate the reaction table with comment liked
*
* @param {string} slug - the comment that is liked
* @param {integer} commentId - the comment that is liked
* @param {integer} userId - the person that reacted to this comment
* @param {string} reaction - the reaction value -like or dislike
*/

export const likeCommentService = async (slug, commentId, userId) => {
try {
const articleExist = await Article.findOne({ where: { slug } });

const commentExist = await Comment.findByPk(commentId);

if (!articleExist) {
return `The article with the specified slug does not exist`;
}

if (!commentExist) {
return 'The comment with the specified id does not exist';
}

const findReaction = await CommentReaction.findOne({
where: {
userId,
commentId
}
});

if (!findReaction) {
await CommentReaction.create({
userId,
commentId
});

const likeCount = await getCommentLikesCount(commentId);

const result = {
likeCount,
message: 'you have successfully liked this comment',
commentId,
userId
};
return result;
}
await CommentReaction.destroy({
where: {
userId,
commentId
}
});

const likeCount = await getCommentLikesCount(commentId);

const result = {
likeCount,
message: 'you have successfully unliked this comment',
commentId,
userId
};
return result;
} catch (error) {
return error.message;
}
};

/**
* @method fetchRatingsService
* - helps fetch all ratings on an article
Expand Down
4 changes: 4 additions & 0 deletions src/services/comment.service.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import moment from 'moment';
import model from '../db/models';
import { getCommentLikesCount } from './article.service';

const { Comment, Article, User } = model;

Expand Down Expand Up @@ -55,6 +56,8 @@ export const getSingleArticleComment = async (id, slug) => {

if (!commentRecord) return false;

const likeCount = await getCommentLikesCount(id);

const { body } = commentRecord.get({ plain: true });
const latestTimestamp = Object.keys(body)[Object.keys(body).length - 1];
const latestComment = body[latestTimestamp];
Expand All @@ -63,6 +66,7 @@ export const getSingleArticleComment = async (id, slug) => {
createdAt: latestTimestamp,
updatedAt: commentRecord.updatedAt,
body: latestComment,
likeCount,
author: {
username: commentRecord.userComment.userName,
bio: commentRecord.userComment.bio,
Expand Down
Loading

0 comments on commit fd2fcdd

Please sign in to comment.