Skip to content

Commit

Permalink
Merge 638b7d8 into ffa16a7
Browse files Browse the repository at this point in the history
  • Loading branch information
UhiriweAudace committed Jul 11, 2019
2 parents ffa16a7 + 638b7d8 commit 2ded693
Show file tree
Hide file tree
Showing 22 changed files with 715 additions and 49 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"regenerator-runtime": "^0.13.2",
"request": "^2.88.0",
"sequelize": "^5.8.7",
"sequelize-cli": "^5.5.0",
"slug": "^1.1.0",
"social-share": "^0.1.0",
"socket.io": "^2.2.0",
Expand Down
118 changes: 118 additions & 0 deletions src/api/controllers/category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import models from '../../sequelize/models';

const { Category, Article } = models;
/**
* @Author - Audace Uhiriwe
*/
class categoryController {
/**
* Admin - create a new category
* @param {object} req - Request.
* @param {object} res - Response.
* @returns {object} - returns a created article
*/
static async createCategory(req, res) {
// check if the category exists
const { categoryName } = req.body;
const categoryExists = await Category.findOne({ where: { categoryName } });
if (categoryExists) {
return res.status(400).send({ error: 'This category is already Exist!' });
}
const data = await Category.NewCategory(req.body);
return res.status(201).send({
message: `This category of ${categoryName} has been successfully added!`,
data
});
}

/**
* Admin - edit an existing category
* @param {object} req - Request.
* @param {object} res - Response.
* @returns {object} - returns an updated article
*/
static async editCategory(req, res) {
// check if the category exists
const { categoryName } = req.body;
const { id } = req.params;
const categoryExists = await Category.findAll({ where: { id } });
if (categoryExists[0].dataValues.categoryName === categoryName) {
return res.status(400).send({
error: 'This category is already exists, Nothing you changed!'
});
}
if (categoryExists === null) {
return res.status(404).send({ error: 'This category Not found!' });
}
const updateCategory = {
categoryName: categoryName || categoryExists[0].dataValues.categoryName
};
await Category.EditCategory(
updateCategory,
categoryExists[0].dataValues.id
);
return res.status(200).send({
message: `This category of ${categoryExists[0].dataValues.categoryName} has been successfully updated to ${categoryName}!`
});
}

/**
* Admin - delete an existing category
* @param {object} req - Request.
* @param {object} res - Response.
* @returns {object} - returns a message
*/
static async deleteCategory(req, res) {
const { id } = req.params;
// check if the category exists
const categoryExists = await Category.findOne({ where: { id } });
if (categoryExists === null) {
return res.status(404).send({ error: 'This category Not found!' });
}
await Category.destroy({ where: { id } });
return res.status(200).send({
message: 'This category has been successfully deleted!'
});
}

/**
* Admin - fetch all categories
* @param {object} req - Request.
* @param {object} res - Response.
* @returns {object} - returns an array of all categories
*/
static async getAllCategory(req, res) {
const categories = await Category.findAll();
if (categories === null) {
return res.status(200).send({ message: 'No Categories found, so far!' });
}
return res.status(200).send({
message: 'Here\'s all categories, so far!',
categories
});
}

/**
* Admin - fetch all articles related to a specific category
* @param {object} req - Request.
* @param {object} res - Response.
* @returns {object} - returns an array which contains all articles related to a specific category
*/
static async fetchAllArticles(req, res) {
const { categoryName } = req.params;
const category = await Category.findOne({ where: { categoryName } });
if (category === null) {
return res.status(404).send({ message: 'This Category Not found!' });
}
const articles = await Article.findAll({ where: { categoryName } });
if (!articles[0]) {
return res.status(200).send({ message: 'No Articles found with this Category, so far!' });
}
return res.status(200).send({
message: 'Here\'s all articles related to that category, so far!',
articles
});
}
}

export default categoryController;
27 changes: 27 additions & 0 deletions src/api/routes/categoryRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Router } from 'express';
import CategoryController from '../controllers/category';
import validateBody from '../../middleware/validateBody';
import Auth from '../../middleware/auth';

const categoryRouter = Router();
const { verifyToken, checkIsAdmin } = Auth;
const {
createCategory,
editCategory,
deleteCategory,
getAllCategory,
fetchAllArticles
} = CategoryController;

categoryRouter.post(
'/',
verifyToken,
checkIsAdmin,
validateBody('category'),
createCategory
);
categoryRouter.put('/:id', verifyToken, checkIsAdmin, editCategory);
categoryRouter.delete('/:id', verifyToken, checkIsAdmin, deleteCategory);
categoryRouter.get('/', getAllCategory);
categoryRouter.get('/:categoryName/articles', fetchAllArticles);
export default categoryRouter;
2 changes: 2 additions & 0 deletions src/api/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import profilesRouter from './profilesRouter';
import articlesRouter from './articlesRouter';
import ratingsRouter from './ratingsRouter';
import bookmarkRouter from './bookmark';
import categoryRouter from './categoryRouter';

const api = express();

Expand All @@ -15,6 +16,7 @@ api.use('/profiles', profilesRouter);
api.use('/articles', articlesRouter);
api.use('/ratings', ratingsRouter);
api.use('/bookmarks', bookmarkRouter);
api.use('/category', categoryRouter);


export default api;
3 changes: 2 additions & 1 deletion src/helpers/articlesHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ArticlesHelper {
*/
static async createNewArticle(req) {
const {
title, body, description, tagList
title, body, description, tagList, categoryName
} = req.body;
const { id } = req.user;
const newSlug = this.createSlug(title);
Expand All @@ -41,6 +41,7 @@ class ArticlesHelper {
authorId: parseInt(id, 10),
readtime,
views: 0,
categoryName: categoryName || 'other'
});
const userInfo = await this.getUserInfo(id);
const { username, bio, image } = userInfo;
Expand Down
15 changes: 9 additions & 6 deletions src/helpers/validationSchemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ const password = Joi.string()
.trim()
.regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/)
.required()
.label('Password is required and must be at least 8 letters containing'
+ ' at least a number a Lowercase letter and an Uppercase letter');
.label('Password is required and must be at least 8 letters containing at least a number a Lowercase letter and an Uppercase letter');
const email = Joi.string()
.trim()
.lowercase()
Expand Down Expand Up @@ -141,9 +140,13 @@ export default {
.trim()
.min(3)
.label('The comment should have at least 3 letters!'),
occurencyNumber: Joi.number()
.label('Occurrency should be a number')


occurencyNumber: Joi.number().label('Occurrency should be a number')
}),
category: Joi.object().keys({
categoryName: Joi.string()
.trim()
.min(3)
.required()
.label('The category Name should be a string which has at least 3 characters and is required!')
})
};
6 changes: 5 additions & 1 deletion src/sequelize/migrations/20190613355309-create-article.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ module.exports = {
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
},
categoryName: {
type: Sequelize.STRING,
allowNull: false
},
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('Articles')
};
26 changes: 26 additions & 0 deletions src/sequelize/migrations/20190710111019-create-category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable no-unused-vars */
module.exports = {
up: (queryInterface, Sequelize) => queryInterface.createTable('Categories', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
categoryName: {
type: Sequelize.STRING
},
articleId: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('Categories')
};
4 changes: 4 additions & 0 deletions src/sequelize/models/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ module.exports = (sequelize, DataTypes) => {
views: {
type: DataTypes.INTEGER
},
categoryName: {
type: DataTypes.STRING,
allowNull: false
},
},
{}
);
Expand Down
18 changes: 18 additions & 0 deletions src/sequelize/models/category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* eslint-disable no-unused-vars */
/* eslint-disable func-names */
module.exports = (sequelize, DataTypes) => {
const Category = sequelize.define('Category', {
categoryName: DataTypes.STRING,
articleId: DataTypes.INTEGER
}, {});

Category.NewCategory = data => Category.create({ categoryName: data.categoryName });
Category.EditCategory = (data, id) => Category.update(
{ categoryName: data.categoryName },
{ where: { id } }
);
Category.associate = function (models) {
// associations can be defined here
};
return Category;
};
19 changes: 18 additions & 1 deletion src/sequelize/seeders/20190618062925-test-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module.exports = {
lastName: 'Audace',
username: 'Audace',
email: 'u.audace@gmail.com',
password: 'Uhiriwe1!',
password: '$2b$08$GCULzAkfmfB/fGyZrnfMSeFG.KdYasuBa2r7z1n.CUFy.KrdnOUdi',
bio: '',
image: '',
dateOfBirth: '12/12/1999',
Expand All @@ -68,6 +68,23 @@ module.exports = {
updatedAt: new Date(),
roles: ['user']
},
{
firstName: 'Uhiriwe1',
lastName: 'Audace1',
username: 'Audace1',
email: 'u1.audace@gmail.com',
password: '$2b$08$NdX6L9irGEltUu.5PnO6P.dIK/4KPoFtn23pVU9HBeH6feTt5e676',
bio: '',
image: '',
dateOfBirth: '12/12/1999',
gender: '',
provider: '',
socialId: '',
verified: 'true',
createdAt: new Date(),
updatedAt: new Date(),
roles: ['admin']
},
{
firstName: 'Eric',
lastName: 'Prestein',
Expand Down
9 changes: 6 additions & 3 deletions src/sequelize/seeders/20190620204605-articles-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ module.exports = {
createdAt: new Date(),
updatedAt: new Date(),
readtime: '2 min',
views: 0
views: 0,
categoryName: 'other'
},
{
slug: '73H99992',
Expand All @@ -26,7 +27,8 @@ module.exports = {
createdAt: new Date(),
updatedAt: new Date(),
readtime: '1min',
views: 0
views: 0,
categoryName: 'other'
},
{
slug: 'This_is_andela_2433546h34',
Expand All @@ -39,7 +41,8 @@ module.exports = {
createdAt: new Date(),
updatedAt: new Date(),
authorId: 4,
views: 0
views: 0,
categoryName: 'other'
}
]),

Expand Down
Loading

0 comments on commit 2ded693

Please sign in to comment.