Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion auth/comparePassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const findUser = ( User, email, password ) => {
if( ! user ) {
reject({})
}

bcrypt.compare( password, user.password, (error, result ) => {
if( result ) {
resolve( user )
Expand Down
45 changes: 45 additions & 0 deletions migrations/20161101213307-create-audit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use strict';
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('Audits', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
table_name: {
type: Sequelize.STRING
},
field_id: {
type: Sequelize.STRING
},
field_name: {
type: Sequelize.STRING
},
old_value: {
type: Sequelize.STRING
},
new_value: {
type: Sequelize.STRING
},
field_type: {
type: Sequelize.STRING
},
user_id: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable('Audits');
}
};
22 changes: 22 additions & 0 deletions models/audit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const returnAuditOptions = require('../src/Auditor')

'use strict';
module.exports = function(sequelize, DataTypes) {
var Audit = sequelize.define('Audit', {
table_name: DataTypes.STRING,
element_id: DataTypes.STRING,
element_name: DataTypes.STRING,
old_value: DataTypes.STRING,
new_value: DataTypes.STRING,
field_type: DataTypes.STRING,
user_id: DataTypes.INTEGER
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
},

}
});
return Audit;
};
62 changes: 42 additions & 20 deletions models/item.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,51 @@
'use strict';

const VALID_PARAMETERS = [ 'completed', 'title', 'description' ]
const returnAuditOptions = require('../src/Auditor')

module.exports = function(sequelize, DataTypes) {
var Item = sequelize.define('Item', {
title: DataTypes.STRING,
description: DataTypes.TEXT,
completed: DataTypes.BOOLEAN,
parent_id: DataTypes.INTEGER,
user_id: DataTypes.INTEGER
}, {
classMethods: {
associate: function(models) {
// associations can be defined here
const Audit = sequelize.models.Audit
const Item = sequelize.define('Item',
{
title: DataTypes.STRING,
description: DataTypes.TEXT,
completed: DataTypes.BOOLEAN,
parent_id: DataTypes.INTEGER,
user_id: DataTypes.INTEGER
},



{
hooks: {
afterCreate: function(item, options) {
let {updateType, data_type} = options
let auditOptions = returnAuditOptions(updateType, item, data_type)
Audit.create(auditOptions[0], {success: true})
},
afterUpdate: function(item, options) {

let {updateType, data_type} = options
let auditOptions = returnAuditOptions(updateType,item, data_type)
Audit.create(auditOptions[0], {success: true})
}
},
filterParameters: params => {
return VALID_PARAMETERS.reduce( (memo, key) => {
if( params[ key ] !== undefined ) {
memo[ key ] = params[ key ]
}

return memo
}, {} )
classMethods: {
associate: function(models) {
// associations can be defined here
},

filterParameters: params => {
return VALID_PARAMETERS.reduce( (memo, key) => {
if( params[ key ] !== undefined ) {
memo[ key ] = params[ key ]
}

return memo
}, {} )
}
}
}
});
);

return Item;
};
2 changes: 1 addition & 1 deletion models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ module.exports = function(sequelize, DataTypes) {
}
});
return User;
};
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"foreman": "^2.0.0",
"jsonwebtoken": "^7.1.9",
"legit": "0.0.5",
"moment": "^2.15.1",
"moment": "^2.15.2",
"morgan": "~1.7.0",
"nodemailer": "^2.6.4",
"passport": "^0.3.2",
Expand Down
5 changes: 4 additions & 1 deletion public/javascripts/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ const params = data =>

const checkJsonForSuccessField = json => {
if( json.success ) {
console.log('checking for json success');
Promise.resolve( json )
} else {
console.log('rejecting for json failure');
Promise.reject( json.message )
}
}
Expand Down Expand Up @@ -74,7 +76,6 @@ const completedClicked = event => {
const element = $( event.target )
const id = element.data( 'id' )
const completed = ! element.data( 'completed' )

fetch( `/items/${id}`, params({ completed: completed } ) )
.then( result => result.json() )
.then( checkJsonForSuccessField )
Expand All @@ -90,6 +91,8 @@ const completedClicked = event => {
)
}



$(document).ready( () => {
$( '.edit-title' ).keypress( titleEdited )
$( '.title > span' ).click( clickToUpdate( 'title' ))
Expand Down
2 changes: 1 addition & 1 deletion routes/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const validateEmail = require( '../src/mail/validate_email' )


const AUTH_OPTIONS = {
successRedirect: '/items',
successRedirect: '/items/weekly',
failureRedirect: '/accounts/login'
}

Expand Down
1 change: 1 addition & 0 deletions routes/accounts/authenticate.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

const token = require( 'jsonwebtoken' )

const authenticate = user => {
Expand Down
26 changes: 22 additions & 4 deletions routes/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const router = express.Router()
const { allItemsQuery, filteredItemsQuery, respondWithItems } = require( './items/item_response' )
const { buildTree } = require( './items/tree_creation' )
const findAllItems = require('./items/find_all_items')
const grabUserStats = require('../src/weekly_report')

router.get( '/', ( request, response ) => {
const { Item } = request.app.get( 'models' )
Expand All @@ -19,20 +20,37 @@ router.post( '/', ( request, response ) => {

const { title, description, parent_id } = request.body

Item.create({ title, description, parent_id, user_id: request.user.id })
Item.create({ title, description, parent_id, user_id: request.user.id }, {updateType: ['create'], individualHooks: true, data_type: 'JSON' })
.then( result => response.redirect( '/items' ))
})

router.get( '/weekly', ( request, response ) => {
const {User, Audit, Item} = request.app.get('models')
const user = request.user
const user_id = user.id
// console.log('uid: ', request.user.id);
grabUserStats( User, user_id, Audit, Item)
.then( userStats => {
let keys = Object.keys(userStats)
response.render('items/weekly_review', {userStats, user, keys})
})
})

router.post( '/:id', ( request, response ) => {
const Item = request.app.get( 'models' ).Item
const {Item, Audit} = request.app.get( 'models' )
const { id } = request.params
const where = { id, user_id: request.user.id }
const valid_params = Item.filterParameters( request.body )
const fields = Object.keys(valid_params)
const data_type_string = `Item.tableAttributes.${fields}.type.constructor.key`
const data_type = eval(data_type_string)

Item.update( Item.filterParameters( request.body ), { where })

Item.update( valid_params, { where, data_type, updateType: fields, individualHooks: true})
.then( result => response.json({ success: true, id }))
.catch( error =>
response.json({ success: false, id, message: error.message })
)
})
})

module.exports = router
58 changes: 58 additions & 0 deletions src/Auditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const returnAuditOptions = (updateType, item, data_type) => {

const auditOptions = updateType.map(type => {
if(type === 'create'){
let options = {
table_name: 'Items',
element_id: item.id,
element_name: 'row',
old_value: 'n/a',
new_value: JSON.stringify(item),
field_type: data_type,
user_id: item.user_id
}
return options
}
if(type === 'completed'){
let options = {
table_name: 'Items',
element_id: item.id,
element_name: type,
old_value: ! item.completed,
new_value: item.completed,
field_type: data_type,
user_id: item.user_id
}
return options
}

if(type === 'title' ){
let options = {
table_name: 'Items',
element_id: item.id,
element_name: type,
old_value: item._previousDataValues.title,
new_value: item.title,
field_type: data_type,
user_id: item.user_id
}
return options
}

if(type === 'description'){
let options = {
table_name: 'Items',
element_id: item.id,
element_name: 'description',
old_value: item._previousDataValues.description,
new_value: item.description,
field_type: data_type,
user_id: item.user_id
}
return options
}
})
return auditOptions
}

module.exports = returnAuditOptions
63 changes: 63 additions & 0 deletions src/weekly_report.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const moment = require('moment')
const today = moment()
const todaysDate = moment()
const minusSevenDays = todaysDate.subtract(7, 'days')

const lengthOfUse = (User, where) =>{
const duration = User.findOne({where})
.then(user => {
return Math.abs(todaysDate.diff(user.createdAt, 'days'))
})
return duration
}

const bulletsCreated = (auditRecords) => {
const createdThisWeek = auditRecords.filter(record => record.createdAt >= minusSevenDays)
return createdThisWeek.length
// ([all items w/ user_id && createdAt(<= today’s date - 7) ].length)
}

const bulletsChanged = (auditRecords) => {
const changedThisWeek = auditRecords.filter(record => record.updatedAt >= minusSevenDays)
return changedThisWeek.length
// ([all items w/ user_id && updatedAt(<= today’s date - 7) ].length)
}

const totalBullets = (auditRecords) => {
const totalBullets = auditRecords.filter(record => {
return record.element_name === 'row' && record.createdAt >= minusSevenDays
})
return totalBullets.length
}

const bulletsCompleted = (auditRecords) => {
const completedItems = auditRecords.filter(record => {
return record.element_name === 'completed' &&
record.new_value == true &&
record.createdAt >= minusSevenDays
})
return completedItems.length
}

const calculateStats = (Audit, user_id) => {
const stats = Audit.findAll({where: {user_id: user_id}})
.then(auditRecords => {
let created = bulletsCreated(auditRecords)
let changed = bulletsChanged(auditRecords)
let completed = bulletsCompleted(auditRecords)
let total = totalBullets(auditRecords)
const userStats = {created, changed, completed, total}
return userStats
})

return stats
}
const grabUserStats = (User, user_id, Audit, Item) => {
const where = {id: user_id}
const userStats = calculateStats(Audit, user_id)
const duration = Promise.resolve(lengthOfUse(User, where)).then(result => result)
userStats.duration = duration
return userStats
}

module.exports = grabUserStats
12 changes: 12 additions & 0 deletions views/items/weekly_review.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
extends ../layouts/authenticated-layout

block content
h1 Your weekly review

p= `Bullets Completed: ${userStats.completed}`
p= `You've used WorkFlowy for ${userStats.lengthOfUse} days.`
p= `Bullets Created: ${userStats.created}`
p= `Bullets Changed: ${userStats.changed} `
p= `Total Bullets: ${userStats.total}`

a.btn.btn-success(href="/items") Go to items