Skip to content

Commit

Permalink
ft-164489793 article notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Frank Harerimana authored and Frank Harerimana committed May 10, 2019
1 parent 99d6a0e commit 7a7be69
Show file tree
Hide file tree
Showing 11 changed files with 210 additions and 44 deletions.
6 changes: 6 additions & 0 deletions controllers/article.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import models from '../models';
import Slug from '../helpers/slug';
import Description from '../helpers/makeDescription';
import ArticleEvents from '../helpers/articleEvents';

const notify = new ArticleEvents();

notify.on('create', args => notify.create(args));

const { article: ArticleModel, user: UserModel } = models;
/**
Expand Down Expand Up @@ -36,6 +41,7 @@ class Article {
title, body, description: descriptData, slug, authorid, taglist
};
const article = await ArticleModel.createArticle(newArticle);
notify.emit('create', newArticle);
return res.status(201).json({ article });
}

Expand Down
107 changes: 107 additions & 0 deletions controllers/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import dotenv from 'dotenv';
import Mailer from '../helpers/mailer';
import models from '../models/index';
import mailLinkMaker from '../helpers/mailLinkMaker';

const { user: UserModel, followers: followersModel, notifications: notificationModel } = models;

dotenv.config();
/**
* this class distributed the notifications
*/
class Notifications {
/**
* @author frank harerimana
* @param {*} userid
* @returns {*} welcome notification
*/
static async userVerifiedAccount(userid) {
const user = await UserModel.findUser(userid);
Mailer.messageMaker(user.email, 'no-reply', 'Thanks for verifying account', `proceed and explore the web
<a href='${process.env.APP_URL}'> here </a>`);
return 'success';
}

/**
* @author frank harerimana
* @param {*} id
* @returns {*} reset password success nitification
*/
static async resetpassword(id) {
const user = await UserModel.findUser(id);
Mailer.messageMaker(user.email, 'no-reply Authors haven', 'Your password has been changed successfully', `
<strong>click the link below to login again<strong>
<a href='${process.env.APP_URL}'>Author's haven</a>`);
return user;
}

/**
* @author frank harerimana
* @param {*} id
* @returns {*} user
*/
static async user(id) {
const res = await UserModel.findUser(id);
return res;
}

/**
* @author frank harerimana
* @param {*} id
* @param {*} message
* @param {*} link
* @returns {*} user
*/
static async NewNotification(id, message, link) {
const res = await notificationModel.newRecord(id, 'article', message, link);
return res;
}

/**
* @author frank harerimana
* @param {*} users
* @param {*} author
* @param {*} slug
* @returns {*} user
*/
static async sendNotifications(users, author, slug) {
const notificationLink = await new mailLinkMaker(`${slug}`).article();
const message = `${author} published a new article`;
for (let i = 0; i < users.length; i += 1) {
this.NewNotification(users[i].id, message, notificationLink);
if (users[i].email === true) Mailer.messageMaker(users[i].email, notificationLink, message, 'read the new article');
}
return 'success';
}

/**
* @author frank harerimana
* @param {*} authorId
* @param {*} slug
* @returns {*} success
*/
static async createArticle(authorId, slug) {
try {
const userArray = [];
const followers = await followersModel.followers(authorId);
followers.map(element => userArray.push(element.dataValues.follower));
const result = [];
// check user emails and notification settings
for (let i = 0; i < userArray.length; i += 1) {
result.push(this.user(userArray[i]));
}
const res = await Promise.all(result);
const users = res.map((element) => {
const respo = element.dataValues;
return respo;
});
const author = await UserModel.findUser(authorId);
await this.sendNotifications(users, author.dataValues.username, slug);
return 'success';
} catch (error) {
return error;
}
}
}

export default Notifications;
38 changes: 0 additions & 38 deletions controllers/userNotification.js

This file was deleted.

21 changes: 21 additions & 0 deletions helpers/articleEvents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable class-methods-use-this */
import { EventEmitter } from 'events';
import notification from '../controllers/notifications';

/**
* notification handler
*/
class ArticleEvents extends EventEmitter {
/**
* @author frank harerimana
* @param {*} args
* @param {*} slug
* @returns {*} call notification controller
*/
create(args) {
notification.createArticle(args.authorid, args.slug);
return 'success';
}
}

export default ArticleEvents;
9 changes: 9 additions & 0 deletions helpers/mailLinkMaker.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ class MailLinkMaker {
async resetPasswordLink() {
return `${process.env.APP_URL}/api/auth/resetpassword/${this.token}`;
}

/**
* @author frank harerimana
* @param {*} identifier
* @return {*} link
*/
async article() {
return `${process.env.APP_URL}/api/articles/${this.token}`;
}
}

export default MailLinkMaker;
2 changes: 1 addition & 1 deletion helpers/userEvents.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable class-methods-use-this */
import { EventEmitter } from 'events';
import userNotification from '../controllers/userNotification';
import userNotification from '../controllers/notifications';

/**
* notification handler
Expand Down
2 changes: 1 addition & 1 deletion migrations/20190424163354-create-notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {
model: 'users', key: 'id', onDelete: 'CASCADE'
}
},
type: {
category: {
type: Sequelize.STRING
},
message: {
Expand Down
1 change: 1 addition & 0 deletions models/followers.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const followersModel = (sequelize, DataTypes) => {
};
Followers.newRecord = (userid, follower) => Followers.create({ userid, follower });
Followers.unfollow = (userid, follower) => Followers.destroy({ where: { userid, follower } });
Followers.followers = userid => Followers.findAll({ where: { userid } });
return Followers;
};
export default followersModel;
6 changes: 3 additions & 3 deletions models/notifications.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
const notificationModel = (sequelize, DataTypes) => {
const Notifications = sequelize.define('notifications', {
userid: DataTypes.INTEGER,
type: DataTypes.STRING,
category: DataTypes.STRING,
message: DataTypes.STRING,
link: DataTypes.TEXT
}, {});
Notifications.associate = (models) => {
Notifications.belongsTo(models.user, { foreignKey: 'userid', onDelete: 'CASCADE' });
};
Notifications.newRecord = (userid, type, message, link) => {
Notifications.newRecord = (userid, category, message, link) => {
Notifications.create({
userid, type, message, link
userid, category, message, link
});
};
return Notifications;
Expand Down
60 changes: 60 additions & 0 deletions test/notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import chai from 'chai';
import debug from 'debug';
import dotenv from 'dotenv';
import faker from 'faker';
import models from '../models/index';
import notification from '../controllers/notifications';

const { notifications: notificationModel } = models;

dotenv.config();
process.env.NODE_ENV = 'test';
chai.should();

const logError = debug('app:*');
const users = [
{
id: 1,
firstname: null,
lastname: null,
username: 'franklisnsv',
email: 'harfrank3@gmailv.com',
inapp_notifications: true,
email_notifications: true
}
];
const data = {
message: faker.lorem.words(),
username: faker.name.findName(),
link: faker.internet.url(),
slug: faker.internet.domainWord()
};
describe('test notification models method', () => {
it('should be able insert notification', async () => {
try {
await notificationModel.newRecord(1, 'article', data.message, data.link);
} catch (error) {
logError(error);
}
});
});

describe('test notification controller mothods', () => {
it('should be able insert notifications', async () => {
try {
await notification.createArticle(1, data.slug);
} catch (error) {
logError(error);
}
});
});

describe('test notification controller methods', () => {
it('should be able send notifications', async () => {
try {
await notification.sendNotifications(users, data.username, data.slug);
} catch (error) {
logError(error);
}
});
});
2 changes: 1 addition & 1 deletion test/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import app from '../index';
import helper from '../helpers/helper';
import userController from '../controllers/user';
import models from '../models/index';
import usernotifications from '../controllers/userNotification';
import usernotifications from '../controllers/notifications';
import userEvents from '../helpers/userEvents';

/**
Expand Down

0 comments on commit 7a7be69

Please sign in to comment.