Skip to content

Commit

Permalink
Merge branch 'develop' into ft-add-search-functionality-1671905
Browse files Browse the repository at this point in the history
  • Loading branch information
chialuka committed Aug 23, 2019
2 parents 843974d + 60e098f commit 0994c03
Show file tree
Hide file tree
Showing 23 changed files with 1,175 additions and 41 deletions.
105 changes: 100 additions & 5 deletions server/controllers/Articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import models from '../database/models';
import { imageUpload, serverResponse, serverError } from '../helpers';
import Tags from './Tags';

const { Article, Like, Dislike } = models;
const {
Article, Like, Dislike, Category
} = models;

/**
* Returns server response for the article like/dislike operation
Expand Down Expand Up @@ -101,25 +103,42 @@ const createLikeOrDislike = async (userAction, userId, article) => {
body,
user: { id }
} = req;
const { status, articleBody, tags } = body;

const { status, articleBody } = body;
let { category } = body;
category = category.toLowerCase();
let { tags } = body;
const publishedAt = status === 'draft' || articleBody === undefined ? null : Date.now();
let createTags;
let categoryDetails = await Category.findOne({
where: { name: category }
});
if (categoryDetails === null) {
categoryDetails = await Category.findOne({
where: { name: 'other' }
});
}
if (categoryDetails.name === 'other' && category !== 'other') tags += `,${category}`;
if (tags) {
createTags = await Tags.create(tags);
const error = Articles.canTag(createTags);
if (error) return serverResponse(res, error.status, error.message);
}
if (file) image = await imageUpload(req);

const myArticle = await Article.create({
...body,
image,
authorId: id,
publishedAt
publishedAt,
categoryId: categoryDetails.id
});

const associateTags = (await Tags.associateArticle(myArticle.id, createTags)) || [];
myArticle.dataValues.tagList = associateTags;
myArticle.dataValues.category = {
id: myArticle.categoryId,
name: categoryDetails.name
};
delete myArticle.dataValues.categoryId;
return serverResponse(res, 200, myArticle.dataValues);
} catch (error) {
return serverError(res);
Expand Down Expand Up @@ -335,6 +354,82 @@ const createLikeOrDislike = async (userAction, userId, article) => {
return serverError(res);
}
}

/**
* update an article
*
* @name update
* @async
* @static
* @memberof Articles
* @param {Object} req express request object
* @param {Object} res express response object
* @returns {JSON} Details of the article and the updated
*/
static async update(req, res) {
try {
let image;
const {
file,
body,
user: { id }
} = req;
if (Object.keys(body).length === 0) {
serverResponse(res, 422, { error: 'request body should not be empty' });
}
let { category } = body;
let { tags } = body;
let categoryDetails;
const { slug } = req.params;
const articleDetails = await Article.findBySlug(slug);
if (articleDetails === null || articleDetails.isArchived) {
return serverResponse(res, 404, { error: 'article not found' });
}
if (category) {
category = category.toLowerCase();
categoryDetails = await Category.findOne({
where: { name: category }
});
if (categoryDetails === null) {
categoryDetails = await Category.findOne({
where: { name: 'other' }
});
}
if (categoryDetails.name === 'other' && category !== 'other') tags += `,${category}`;
articleDetails.categoryId = categoryDetails.id;
}
let createTags;
if (tags) {
createTags = await Tags.create(tags);
const error = Articles.canTag(createTags);
if (error) return serverResponse(res, error.status, error.message);
await Tags.associateArticle(articleDetails.id, createTags);
}
if (file) image = await imageUpload(req);
const { status, articleBody } = body;
const publishedAt = status === 'draft' || articleBody === undefined ? null : Date.now();
const updated = await Article.update(
{
...body,
publishedAt,
image,
categoryId: articleDetails.categoryId
},
{ where: { slug, authorId: id }, returning: true }
);
if (!updated[0]) {
return serverResponse(res, 403, { message: 'article not updated' });
}
const updatedArticle = updated[1][0].dataValues;
const aritcleCategory = await articleDetails.getCategory();
const updatedTags = await articleDetails.getTags();
updatedArticle.tagList = updatedTags.map(({ name }) => name);
updatedArticle.category = aritcleCategory;
return serverResponse(res, 200, { ...updatedArticle });
} catch (error) {
return serverError(res);
}
}
}

export default Articles;
82 changes: 82 additions & 0 deletions server/controllers/Comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,88 @@ class Comments {
serverError(res);
}
}

/**
* @name delete
* @async
* @static
* @memberof Comments
* @param {Object} req express request object
* @param {Object} res express response object
* @returns {JSON} JSON object with message on deleted message
*/
static async delete(req, res) {
try {
const { slug, id } = req.params;
const { id: userId } = req.user;
const article = await Article.findBySlug(slug);
if (!article) {
return serverResponse(res, 404, { error: 'article not found' });
}
const articleId = article.id;
const comment = await Comment.findOne({ where: { id, articleId } });
if (!comment) {
return serverResponse(res, 404, { error: 'comment not found' });
}

const deletedComment = await Comment.destroy({
where: { id, articleId, userId }
});

if (!deletedComment) {
return serverResponse(res, 403, {
error: "you don't have permission to access this content"
});
}

return serverResponse(res, 200, { message: 'comment deleted' });
} catch (error) {
serverError(res);
}
}

/**
* @name update
* @async
* @static
* @memberof Comments
* @param {Object} req express request object
* @param {Object} res express response object
* @returns {JSON} JSON object with details of update message
*/
static async update(req, res) {
try {
const { slug, id } = req.params;
const { id: userId } = req.user;
let { comment } = req.body;

const article = await Article.findBySlug(slug);
if (!article) {
return serverResponse(res, 404, { error: 'article not found' });
}

const articleId = article.id;
const commentData = await Comment.findOne({ where: { id, articleId } });
if (!commentData) {
return serverResponse(res, 404, { error: 'comment not found' });
}

const [rowsUpdated, [updatedComment]] = await Comment.update(
{ comment },
{ returning: true, where: { id, userId, articleId } }
);
if (rowsUpdated < 1) {
return serverResponse(res, 403, {
error: "you don't have permission to access this content"
});
}

comment = updatedComment.dataValues;
return serverResponse(res, 200, { message: 'comment updated', comment });
} catch (error) {
serverError(res);
}
}
}

export default Comments;
13 changes: 12 additions & 1 deletion server/database/migrations/20190813135136-create-article.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,18 @@ export default {
type: Sequelize.TEXT
},
authorId: {
type: Sequelize.INTEGER
type: Sequelize.INTEGER,
references: {
model: 'Users',
key: 'id'
}
},
categoryId: {
type: Sequelize.INTEGER,
references: {
model: 'Categories',
key: 'id'
}
},
likesCount: {
type: Sequelize.INTEGER
Expand Down
13 changes: 13 additions & 0 deletions server/database/models/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ export default (sequelize, DataTypes) => {
type: DataTypes.TEXT,
allowNull: true
},
authorId: {
type: DataTypes.INTEGER,
allowNull: false
},
categoryId: {
type: DataTypes.INTEGER,
allowNull: false
},
likesCount: {
type: DataTypes.INTEGER,
defaultValue: 0,
Expand Down Expand Up @@ -119,6 +127,11 @@ export default (sequelize, DataTypes) => {
contentType: 'article'
}
});
Article.belongsTo(models.Category, {
foreignKey: 'categoryId',
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
});
};

SequelizeSlugify.slugifyModel(Article, {
Expand Down
5 changes: 5 additions & 0 deletions server/database/models/category.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export default (sequelize, DataTypes) => {
through: 'UserCategory',
as: 'users'
});
Category.hasMany(models.Article, {
foreignKey: 'categoryId',
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
});
};
return Category;
};
15 changes: 10 additions & 5 deletions server/database/seeds/20190731140728-categories-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@ export default {
'Categories',
[
{
name: 'Arts & Entertainment',
name: 'other',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'Industry',
name: 'arts & entertainment',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'Innovation & Tech',
name: 'industry',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'Life',
name: 'innovation & tech',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'Society',
name: 'life',
createdAt: new Date(),
updatedAt: new Date()
},
{
name: 'society',
createdAt: new Date(),
updatedAt: new Date()
}
Expand Down
Loading

0 comments on commit 0994c03

Please sign in to comment.