From 9f5c840082a680fee78ddbc5ce44cb0aea259b31 Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Mon, 31 Oct 2016 14:30:28 -0700 Subject: [PATCH 01/12] added migration for CompletedItems table --- .../20161031211644-create-completed-items.js | 30 +++++++++++++++++++ models/completeditems.js | 14 +++++++++ 2 files changed, 44 insertions(+) create mode 100644 migrations/20161031211644-create-completed-items.js create mode 100644 models/completeditems.js diff --git a/migrations/20161031211644-create-completed-items.js b/migrations/20161031211644-create-completed-items.js new file mode 100644 index 0000000..f29d8cb --- /dev/null +++ b/migrations/20161031211644-create-completed-items.js @@ -0,0 +1,30 @@ +'use strict'; +module.exports = { + up: function(queryInterface, Sequelize) { + return queryInterface.createTable('CompletedItems', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + item_id: { + type: Sequelize.INTEGER + }, + completedBy: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: function(queryInterface, Sequelize) { + return queryInterface.dropTable('CompletedItems'); + } +}; \ No newline at end of file diff --git a/models/completeditems.js b/models/completeditems.js new file mode 100644 index 0000000..6df7b14 --- /dev/null +++ b/models/completeditems.js @@ -0,0 +1,14 @@ +'use strict'; +module.exports = function(sequelize, DataTypes) { + var CompletedItems = sequelize.define('CompletedItems', { + item_id: DataTypes.INTEGER, + completedBy: DataTypes.INTEGER + }, { + classMethods: { + associate: function(models) { + // associations can be defined here + } + } + }); + return CompletedItems; +}; \ No newline at end of file From 15e999a9a6322b650718fcafc78c67a93c7bd973 Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Tue, 1 Nov 2016 10:30:39 -0700 Subject: [PATCH 02/12] wip - switching branches to push previous branch for PR --- ...s.js => 20161101164810-create-completed-items.js} | 2 +- models/completeditems.js | 12 ++++++++++-- public/javascripts/items.js | 3 ++- routes/items.js | 3 +++ 4 files changed, 16 insertions(+), 4 deletions(-) rename migrations/{20161031211644-create-completed-items.js => 20161101164810-create-completed-items.js} (96%) diff --git a/migrations/20161031211644-create-completed-items.js b/migrations/20161101164810-create-completed-items.js similarity index 96% rename from migrations/20161031211644-create-completed-items.js rename to migrations/20161101164810-create-completed-items.js index f29d8cb..f7c585d 100644 --- a/migrations/20161031211644-create-completed-items.js +++ b/migrations/20161101164810-create-completed-items.js @@ -11,7 +11,7 @@ module.exports = { item_id: { type: Sequelize.INTEGER }, - completedBy: { + user_id: { type: Sequelize.INTEGER }, createdAt: { diff --git a/models/completeditems.js b/models/completeditems.js index 6df7b14..fc9cc0e 100644 --- a/models/completeditems.js +++ b/models/completeditems.js @@ -2,13 +2,21 @@ module.exports = function(sequelize, DataTypes) { var CompletedItems = sequelize.define('CompletedItems', { item_id: DataTypes.INTEGER, - completedBy: DataTypes.INTEGER + user_id: DataTypes.INTEGER }, { classMethods: { associate: function(models) { // associations can be defined here + }, + toggle: (item_id, user_id) => { + this.findOrCreate(item_id) + .then(result => { + if(result[1] === false){ + this.delete(result[0].id) + } else {return} + }) } } }); return CompletedItems; -}; \ No newline at end of file +}; diff --git a/public/javascripts/items.js b/public/javascripts/items.js index 5fd9cbb..ce5e74c 100644 --- a/public/javascripts/items.js +++ b/public/javascripts/items.js @@ -74,7 +74,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 ) @@ -90,6 +89,8 @@ const completedClicked = event => { ) } + + $(document).ready( () => { $( '.edit-title' ).keypress( titleEdited ) $( '.title > span' ).click( clickToUpdate( 'title' )) diff --git a/routes/items.js b/routes/items.js index d505c34..6480beb 100644 --- a/routes/items.js +++ b/routes/items.js @@ -25,9 +25,12 @@ router.post( '/', ( request, response ) => { router.post( '/:id', ( request, response ) => { const Item = request.app.get( 'models' ).Item + const CompletedItems = request.app.get( 'models' ).CompletedItems const { id } = request.params const where = { id, user_id: request.user.id } + CompletedItems.toggle({item_id: id, completedBy: request.user.id}) + Item.update( Item.filterParameters( request.body ), { where }) .then( result => response.json({ success: true, id })) .catch( error => From 03542ea13aec5156ef98a651a2df0d6a79e64f2a Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Tue, 1 Nov 2016 13:41:52 -0700 Subject: [PATCH 03/12] wip - got route set up for weekly review display at login --- routes/accounts.js | 2 +- routes/accounts/authenticate.js | 1 + routes/items.js | 4 ++++ views/items/weekly_review.pug | 5 +++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 views/items/weekly_review.pug diff --git a/routes/accounts.js b/routes/accounts.js index 1612ab9..6a8fc9a 100644 --- a/routes/accounts.js +++ b/routes/accounts.js @@ -8,7 +8,7 @@ const validateEmail = require( '../src/mail/validate_email' ) const AUTH_OPTIONS = { - successRedirect: '/items', + successRedirect: '/items/weekly', failureRedirect: '/accounts/login' } diff --git a/routes/accounts/authenticate.js b/routes/accounts/authenticate.js index b9b3ac5..e8b7816 100644 --- a/routes/accounts/authenticate.js +++ b/routes/accounts/authenticate.js @@ -1,3 +1,4 @@ + const token = require( 'jsonwebtoken' ) const authenticate = user => { diff --git a/routes/items.js b/routes/items.js index 6480beb..a6d45c4 100644 --- a/routes/items.js +++ b/routes/items.js @@ -23,6 +23,10 @@ router.post( '/', ( request, response ) => { .then( result => response.redirect( '/items' )) }) +router.get( '/weekly', ( request, response ) => { + response.render('items/weekly_review', {user: request.user}) +}) + router.post( '/:id', ( request, response ) => { const Item = request.app.get( 'models' ).Item const CompletedItems = request.app.get( 'models' ).CompletedItems diff --git a/views/items/weekly_review.pug b/views/items/weekly_review.pug new file mode 100644 index 0000000..971ed59 --- /dev/null +++ b/views/items/weekly_review.pug @@ -0,0 +1,5 @@ +extends ../layouts/authenticated-layout + +block content + h1 Your weekly review + a.btn.btn-success(href="/items") Go to items From 52a7cf549aecb7a7bebdec33620a66c8415cd7cf Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Tue, 1 Nov 2016 14:37:22 -0700 Subject: [PATCH 04/12] created audit table migration --- migrations/20161101213307-create-audit.js | 45 +++++++++++++++++++++++ models/audit.js | 19 ++++++++++ 2 files changed, 64 insertions(+) create mode 100644 migrations/20161101213307-create-audit.js create mode 100644 models/audit.js diff --git a/migrations/20161101213307-create-audit.js b/migrations/20161101213307-create-audit.js new file mode 100644 index 0000000..a1d09b8 --- /dev/null +++ b/migrations/20161101213307-create-audit.js @@ -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'); + } +}; \ No newline at end of file diff --git a/models/audit.js b/models/audit.js new file mode 100644 index 0000000..99a3f21 --- /dev/null +++ b/models/audit.js @@ -0,0 +1,19 @@ +'use strict'; +module.exports = function(sequelize, DataTypes) { + var Audit = sequelize.define('Audit', { + table_name: DataTypes.STRING, + field_id: DataTypes.STRING, + field_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; +}; \ No newline at end of file From 8d05e69e9a992a1c7e2b0ba3cf25b02a1bc9626a Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Tue, 1 Nov 2016 17:11:02 -0700 Subject: [PATCH 05/12] wip Item.completed field creates audit trail on update --- .../20161101164810-create-completed-items.js | 30 ------------------- models/completeditems.js | 22 -------------- routes/items.js | 10 +++++-- 3 files changed, 8 insertions(+), 54 deletions(-) delete mode 100644 migrations/20161101164810-create-completed-items.js delete mode 100644 models/completeditems.js diff --git a/migrations/20161101164810-create-completed-items.js b/migrations/20161101164810-create-completed-items.js deleted file mode 100644 index f7c585d..0000000 --- a/migrations/20161101164810-create-completed-items.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -module.exports = { - up: function(queryInterface, Sequelize) { - return queryInterface.createTable('CompletedItems', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER - }, - item_id: { - type: Sequelize.INTEGER - }, - user_id: { - type: Sequelize.INTEGER - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE - } - }); - }, - down: function(queryInterface, Sequelize) { - return queryInterface.dropTable('CompletedItems'); - } -}; \ No newline at end of file diff --git a/models/completeditems.js b/models/completeditems.js deleted file mode 100644 index fc9cc0e..0000000 --- a/models/completeditems.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; -module.exports = function(sequelize, DataTypes) { - var CompletedItems = sequelize.define('CompletedItems', { - item_id: DataTypes.INTEGER, - user_id: DataTypes.INTEGER - }, { - classMethods: { - associate: function(models) { - // associations can be defined here - }, - toggle: (item_id, user_id) => { - this.findOrCreate(item_id) - .then(result => { - if(result[1] === false){ - this.delete(result[0].id) - } else {return} - }) - } - } - }); - return CompletedItems; -}; diff --git a/routes/items.js b/routes/items.js index a6d45c4..b004c8d 100644 --- a/routes/items.js +++ b/routes/items.js @@ -29,17 +29,23 @@ router.get( '/weekly', ( request, response ) => { router.post( '/:id', ( request, response ) => { const Item = request.app.get( 'models' ).Item - const CompletedItems = request.app.get( 'models' ).CompletedItems + const Audit = request.app.get( 'models' ).Audit const { id } = request.params const where = { id, user_id: request.user.id } + console.log(request.body); - CompletedItems.toggle({item_id: id, completedBy: request.user.id}) Item.update( Item.filterParameters( request.body ), { where }) .then( result => response.json({ success: true, id })) .catch( error => response.json({ success: false, id, message: error.message }) ) + + if ( request.body.hasOwnProperty('completed') ) { + let old_value = ! request.body.completed + console.log(old_value); + Audit.create({table_name: 'Items', field_id: id, field_name: 'completed', old_value: old_value.toString() , new_value: request.body.completed.toString() , field_type: 'BOOLEAN', user_id: request.user.id}) + } }) module.exports = router From 0efc65461f6853e9c52fd1eb779bc10b3142df9f Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Wed, 2 Nov 2016 12:00:17 -0700 Subject: [PATCH 06/12] wip - pushing to work with tanner --- models/item.js | 41 ++++++++++++++++++++++++++++++++++------- routes/items.js | 44 ++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/models/item.js b/models/item.js index dca2d75..275a93b 100644 --- a/models/item.js +++ b/models/item.js @@ -9,19 +9,46 @@ module.exports = function(sequelize, DataTypes) { completed: DataTypes.BOOLEAN, parent_id: DataTypes.INTEGER, user_id: DataTypes.INTEGER - }, { + }, + + { + hooks: { + afterCreate: function(item, options) { + Audit.create({ + table_name: 'Items', + field_id: options.id, + field_name: 'completed', + old_value: 'n/a', + new_value: options.new_value, + field_type: options.field_type, + user_id: request.user.id + }) + }, + afterDestroy: function(user, options) { + user.username = 'Toni' + }, + afterUpdate: function(user, options) { + user.username = 'Toni' + }, + + }, 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 new Promise( (resolve, reject) => { + VALID_PARAMETERS.reduce( (memo, key) => { + if( params[ key ] === undefined ) { + reject({}) + }else{ + memo[ key ] = params[ key ] + resolve( memo ) + } - return memo - }, {} ) + }, {} ) + }) } } }); diff --git a/routes/items.js b/routes/items.js index b004c8d..4f7cded 100644 --- a/routes/items.js +++ b/routes/items.js @@ -28,24 +28,44 @@ router.get( '/weekly', ( request, response ) => { }) router.post( '/:id', ( request, response ) => { - const Item = request.app.get( 'models' ).Item - const Audit = request.app.get( 'models' ).Audit + const { Item, Audit } = request.app.get( 'models' ) const { id } = request.params const where = { id, user_id: request.user.id } - console.log(request.body); + console.log('request.body: ' , request.body , ' where: ' , where); - - Item.update( Item.filterParameters( request.body ), { where }) - .then( result => response.json({ success: true, id })) - .catch( error => - response.json({ success: false, id, message: error.message }) + Item.filterParameters( request.body ) + .then(result => + Item.update( result, { where }) //request.body = {completed: true} + .then( jsonResponse => { + console.log('jsonResponse',jsonResponse); + response.json({ success: true, id }) + }) + .catch( error => response.json({ success: false, id, message: error.message })) ) if ( request.body.hasOwnProperty('completed') ) { - let old_value = ! request.body.completed - console.log(old_value); - Audit.create({table_name: 'Items', field_id: id, field_name: 'completed', old_value: old_value.toString() , new_value: request.body.completed.toString() , field_type: 'BOOLEAN', user_id: request.user.id}) - } + let old_value = ! request.body.completed + console.log('old_value',old_value); + Audit.create({ + table_name: 'Items', + field_id: id, + field_name: 'completed', + old_value: old_value.toString(), + new_value: request.body.completed.toString(), + field_type: 'BOOLEAN', + user_id: request.user.id + }) + } + + if ( request.body.hasOwnProperty('title') ){ + console.log('title changed'); + } + + if (request.body.hasOwnProperty('description') ){ + console.log('description changed'); + } + + }) module.exports = router From 5ce81750c2b0873407af37ba88ccf8aed257bf8d Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Wed, 2 Nov 2016 14:57:32 -0700 Subject: [PATCH 07/12] looking for feedback on using hooks. --- models/item.js | 106 ++++++++++++++++++++++++++++-------------------- routes/items.js | 37 ++++++++--------- 2 files changed, 79 insertions(+), 64 deletions(-) diff --git a/models/item.js b/models/item.js index 275a93b..20bdd62 100644 --- a/models/item.js +++ b/models/item.js @@ -1,56 +1,72 @@ 'use strict'; - const VALID_PARAMETERS = [ 'completed', 'title', 'description' ] 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 - }, - - { - hooks: { - afterCreate: function(item, options) { - Audit.create({ - table_name: 'Items', - field_id: options.id, - field_name: 'completed', - old_value: 'n/a', - new_value: options.new_value, - field_type: options.field_type, - user_id: request.user.id - }) - }, - afterDestroy: function(user, options) { - user.username = 'Toni' - }, - afterUpdate: function(user, options) { - user.username = 'Toni' - }, - + const 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 + + + + { + hooks: { + // afterCreate: function(item, options) { + // }, + // afterDestroy: function(user, options) { + // user.username = 'Toni' + // }, + afterUpdate: function(item, options) { + const Audit = sequelize.import('../models/audit'); + + Audit.create({ + table_name: 'Items', + field_id: options.where.id, + field_name: 'completed', + old_value: 'n/a', + new_value: options.new_value, + field_type: options.field_type, + user_id: options.user_id + }) + } }, + classMethods: { + associate: function(models) { + // associations can be defined here + }, - filterParameters: params => { - return new Promise( (resolve, reject) => { - VALID_PARAMETERS.reduce( (memo, key) => { - if( params[ key ] === undefined ) { - reject({}) - }else{ - memo[ key ] = params[ key ] - resolve( memo ) - } - - }, {} ) - }) + filterParameters: params => { + return new Promise( (resolve, reject) => { + VALID_PARAMETERS.reduce( (memo, key) => { + if( params[ key ] === undefined ) { + reject({}) + }else{ + memo[ key ] = params[ key ] + resolve( memo ) + } + + }, {} ) + }) + } } } - }); + ); + + console.log("in models/items.js") + + Item.beforeUpdate((item, options) => { + console.log("In beforeUpdate hook:"); + console.log('\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n',item ); + }) + + // Item.afterUpdate((item, options) => { + // console.log("In afterUpdate hook:"); + // console.log(item, '\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n'); + // }) + return Item; }; diff --git a/routes/items.js b/routes/items.js index 4f7cded..c330d78 100644 --- a/routes/items.js +++ b/routes/items.js @@ -28,35 +28,34 @@ router.get( '/weekly', ( request, response ) => { }) router.post( '/:id', ( request, response ) => { - const { Item, Audit } = request.app.get( 'models' ) + const { Item } = request.app.get( 'models' ) const { id } = request.params const where = { id, user_id: request.user.id } console.log('request.body: ' , request.body , ' where: ' , where); Item.filterParameters( request.body ) - .then(result => - Item.update( result, { where }) //request.body = {completed: true} + .then(result => { + Item.update( result, { where, individualHooks: true }) //request.body = {completed: true} .then( jsonResponse => { - console.log('jsonResponse',jsonResponse); response.json({ success: true, id }) }) .catch( error => response.json({ success: false, id, message: error.message })) - ) - - if ( request.body.hasOwnProperty('completed') ) { - let old_value = ! request.body.completed - console.log('old_value',old_value); - Audit.create({ - table_name: 'Items', - field_id: id, - field_name: 'completed', - old_value: old_value.toString(), - new_value: request.body.completed.toString(), - field_type: 'BOOLEAN', - user_id: request.user.id }) - } - + + // if ( request.body.hasOwnProperty('completed') ) { + // let old_value = ! request.body.completed + // console.log('old_value',old_value); + // Audit.create({ + // table_name: 'Items', + // field_id: id, + // field_name: 'completed', + // old_value: old_value.toString(), + // new_value: request.body.completed.toString(), + // field_type: 'BOOLEAN', + // user_id: request.user.id + // }) + // } + if ( request.body.hasOwnProperty('title') ){ console.log('title changed'); } From 54c4564cfe3b758288977147a71de76599aebcfb Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Thu, 3 Nov 2016 13:49:31 -0700 Subject: [PATCH 08/12] wip --- models/audit.js | 6 ++-- models/item.js | 46 ++++++++----------------------- public/javascripts/items.js | 2 ++ routes/items.js | 24 +++++++--------- src/Auditor.js | 55 +++++++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+), 51 deletions(-) create mode 100644 src/Auditor.js diff --git a/models/audit.js b/models/audit.js index 99a3f21..dbc9877 100644 --- a/models/audit.js +++ b/models/audit.js @@ -2,8 +2,8 @@ module.exports = function(sequelize, DataTypes) { var Audit = sequelize.define('Audit', { table_name: DataTypes.STRING, - field_id: DataTypes.STRING, - field_name: DataTypes.STRING, + element_id: DataTypes.STRING, + element_name: DataTypes.STRING, old_value: DataTypes.STRING, new_value: DataTypes.STRING, field_type: DataTypes.STRING, @@ -16,4 +16,4 @@ module.exports = function(sequelize, DataTypes) { } }); return Audit; -}; \ No newline at end of file +}; diff --git a/models/item.js b/models/item.js index 20bdd62..34bbfa4 100644 --- a/models/item.js +++ b/models/item.js @@ -1,5 +1,6 @@ 'use strict'; const VALID_PARAMETERS = [ 'completed', 'title', 'description' ] +const returnAuditOptions = require('../src/Auditor') module.exports = function(sequelize, DataTypes) { const Item = sequelize.define('Item', @@ -21,17 +22,10 @@ module.exports = function(sequelize, DataTypes) { // user.username = 'Toni' // }, afterUpdate: function(item, options) { - const Audit = sequelize.import('../models/audit'); - - Audit.create({ - table_name: 'Items', - field_id: options.where.id, - field_name: 'completed', - old_value: 'n/a', - new_value: options.new_value, - field_type: options.field_type, - user_id: options.user_id - }) + const Audit = sequelize.models.Audit + let {updateType, data_type} = options + let auditOptions = returnAuditOptions(updateType,item, data_type) + Audit.create(auditOptions[0], {success: true}) } }, classMethods: { @@ -40,33 +34,17 @@ module.exports = function(sequelize, DataTypes) { }, filterParameters: params => { - return new Promise( (resolve, reject) => { - VALID_PARAMETERS.reduce( (memo, key) => { - if( params[ key ] === undefined ) { - reject({}) - }else{ - memo[ key ] = params[ key ] - resolve( memo ) - } - - }, {} ) - }) + console.log(params); + return VALID_PARAMETERS.reduce( (memo, key) => { + if( params[ key ] !== undefined ) { + memo[ key ] = params[ key ] + } + return memo + }, {} ) } } } ); - console.log("in models/items.js") - - Item.beforeUpdate((item, options) => { - console.log("In beforeUpdate hook:"); - console.log('\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n',item ); - }) - - // Item.afterUpdate((item, options) => { - // console.log("In afterUpdate hook:"); - // console.log(item, '\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n'); - // }) - return Item; }; diff --git a/public/javascripts/items.js b/public/javascripts/items.js index ce5e74c..e20c323 100644 --- a/public/javascripts/items.js +++ b/public/javascripts/items.js @@ -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 ) } } diff --git a/routes/items.js b/routes/items.js index c330d78..7dc9450 100644 --- a/routes/items.js +++ b/routes/items.js @@ -31,11 +31,17 @@ router.post( '/:id', ( request, response ) => { const { Item } = request.app.get( 'models' ) const { id } = request.params const where = { id, user_id: request.user.id } - console.log('request.body: ' , request.body , ' where: ' , where); - +console.log('pre',request.body); Item.filterParameters( request.body ) - .then(result => { - Item.update( result, { where, individualHooks: true }) //request.body = {completed: true} + .then( result => { + console.log('post',result); + const fields = Object.keys(result) + return {result, fields} + }) + .then(({result, fields}) => { + let data_type_string = `Item.tableAttributes.${fields}.type.constructor.key` + let data_type = eval(data_type_string) + Item.update( result, { where, individualHooks: true, updateType: fields , data_type: data_type }) //request.body = {completed: true} .then( jsonResponse => { response.json({ success: true, id }) }) @@ -55,16 +61,6 @@ router.post( '/:id', ( request, response ) => { // user_id: request.user.id // }) // } - - if ( request.body.hasOwnProperty('title') ){ - console.log('title changed'); - } - - if (request.body.hasOwnProperty('description') ){ - console.log('description changed'); - } - - }) module.exports = router diff --git a/src/Auditor.js b/src/Auditor.js new file mode 100644 index 0000000..5bba6f8 --- /dev/null +++ b/src/Auditor.js @@ -0,0 +1,55 @@ +const returnAuditOptions = (updateType, item, data_type) => { + console.log('returning Audit Options',updateType, data_type); + const auditOptions = updateType.map(type => { + console.log('type',type, 'data_type', data_type); + if(type === 'completed'){ + console.log('in 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 + } + console.log('>>>>>>',item._previousDataValues.title); + return options + } + + if(type === 'title' ){ + console.log('in title'); + let options = { + table_name: 'Items', + element_id: item.id, + element_name: type, + old_value: item._previousDataValues.title, + new_value: item.title, + field_type: datatype, + user_id: item.user_id + } + console.log('title',options); + return options + } + + if(type === 'description'){ + let options = { + table_name: 'Items', + element_id: options.where.id, + element_name: 'description', + old_value: ! item._previousDataValues, + new_value: item.description, + field_type: datatype, + user_id: options.where.user_id + } + console.log('description', options); + return options + } + + + }) + console.log('auditOptions',auditOptions); + return auditOptions +} + +module.exports = returnAuditOptions From 0e32d61ce643144dd3152fcd299265e0d06451b6 Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Thu, 3 Nov 2016 21:14:39 -0700 Subject: [PATCH 09/12] audits working for updates --- models/audit.js | 6 +++++- models/item.js | 12 ++++++------ routes/items.js | 45 +++++++++++++-------------------------------- src/Auditor.js | 16 +++++++--------- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/models/audit.js b/models/audit.js index dbc9877..95906f4 100644 --- a/models/audit.js +++ b/models/audit.js @@ -1,3 +1,5 @@ +const returnAuditOptions = require('../src/Auditor') + 'use strict'; module.exports = function(sequelize, DataTypes) { var Audit = sequelize.define('Audit', { @@ -12,7 +14,9 @@ module.exports = function(sequelize, DataTypes) { classMethods: { associate: function(models) { // associations can be defined here - } + }, + + getAuditOptions: () => returnAuditOptions } }); return Audit; diff --git a/models/item.js b/models/item.js index 34bbfa4..03ac417 100644 --- a/models/item.js +++ b/models/item.js @@ -34,12 +34,12 @@ module.exports = function(sequelize, DataTypes) { }, filterParameters: params => { - console.log(params); - return VALID_PARAMETERS.reduce( (memo, key) => { - if( params[ key ] !== undefined ) { - memo[ key ] = params[ key ] - } - return memo + return VALID_PARAMETERS.reduce( (memo, key) => { + if( params[ key ] !== undefined ) { + memo[ key ] = params[ key ] + } + + return memo }, {} ) } } diff --git a/routes/items.js b/routes/items.js index 7dc9450..3e86ea6 100644 --- a/routes/items.js +++ b/routes/items.js @@ -28,39 +28,20 @@ router.get( '/weekly', ( request, response ) => { }) router.post( '/:id', ( request, response ) => { - const { Item } = request.app.get( 'models' ) + const {Item, Audit} = request.app.get( 'models' ) const { id } = request.params const where = { id, user_id: request.user.id } -console.log('pre',request.body); - Item.filterParameters( request.body ) - .then( result => { - console.log('post',result); - const fields = Object.keys(result) - return {result, fields} - }) - .then(({result, fields}) => { - let data_type_string = `Item.tableAttributes.${fields}.type.constructor.key` - let data_type = eval(data_type_string) - Item.update( result, { where, individualHooks: true, updateType: fields , data_type: data_type }) //request.body = {completed: true} - .then( jsonResponse => { - response.json({ success: true, id }) - }) - .catch( error => response.json({ success: false, id, message: error.message })) - }) - - // if ( request.body.hasOwnProperty('completed') ) { - // let old_value = ! request.body.completed - // console.log('old_value',old_value); - // Audit.create({ - // table_name: 'Items', - // field_id: id, - // field_name: 'completed', - // old_value: old_value.toString(), - // new_value: request.body.completed.toString(), - // field_type: 'BOOLEAN', - // user_id: request.user.id - // }) - // } -}) + const valid_params = Item.filterParameters( request.body ) + const fields = Object.keys(valid_params) + let data_type_string = `Item.tableAttributes.${fields}.type.constructor.key` + const data_type = eval(data_type_string) + + + 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 diff --git a/src/Auditor.js b/src/Auditor.js index 5bba6f8..7ea59f3 100644 --- a/src/Auditor.js +++ b/src/Auditor.js @@ -18,35 +18,33 @@ const returnAuditOptions = (updateType, item, data_type) => { } if(type === 'title' ){ - console.log('in title'); + console.log('type: ', item._previousDataValues.title ); let options = { table_name: 'Items', element_id: item.id, element_name: type, old_value: item._previousDataValues.title, new_value: item.title, - field_type: datatype, + field_type: data_type, user_id: item.user_id } - console.log('title',options); + console.log('title: ',options); return options } if(type === 'description'){ let options = { table_name: 'Items', - element_id: options.where.id, + element_id: item.id, element_name: 'description', - old_value: ! item._previousDataValues, + old_value: item._previousDataValues.description, new_value: item.description, - field_type: datatype, - user_id: options.where.user_id + field_type: data_type, + user_id: item.user_id } console.log('description', options); return options } - - }) console.log('auditOptions',auditOptions); return auditOptions From 45d557c025ddb1e8be602e3520addf9512331b53 Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Fri, 4 Nov 2016 11:39:27 -0700 Subject: [PATCH 10/12] weekly review numbers passing to page - still need labeling and styling --- auth/comparePassword.js | 2 +- models/audit.js | 1 - models/item.js | 13 +++---- models/user.js | 2 +- package.json | 2 +- routes/items.js | 13 +++++-- src/Auditor.js | 16 ++++++++- src/weekly_report.js | 68 +++++++++++++++++++++++++++++++++++ views/items/weekly_review.pug | 3 +- 9 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 src/weekly_report.js diff --git a/auth/comparePassword.js b/auth/comparePassword.js index f2976d2..adeb464 100644 --- a/auth/comparePassword.js +++ b/auth/comparePassword.js @@ -7,7 +7,7 @@ const findUser = ( User, email, password ) => { if( ! user ) { reject({}) } - + bcrypt.compare( password, user.password, (error, result ) => { if( result ) { resolve( user ) diff --git a/models/audit.js b/models/audit.js index 95906f4..e4a65e2 100644 --- a/models/audit.js +++ b/models/audit.js @@ -16,7 +16,6 @@ module.exports = function(sequelize, DataTypes) { // associations can be defined here }, - getAuditOptions: () => returnAuditOptions } }); return Audit; diff --git a/models/item.js b/models/item.js index 03ac417..ec27e85 100644 --- a/models/item.js +++ b/models/item.js @@ -3,6 +3,7 @@ const VALID_PARAMETERS = [ 'completed', 'title', 'description' ] const returnAuditOptions = require('../src/Auditor') module.exports = function(sequelize, DataTypes) { + const Audit = sequelize.models.Audit const Item = sequelize.define('Item', { title: DataTypes.STRING, @@ -16,13 +17,13 @@ module.exports = function(sequelize, DataTypes) { { hooks: { - // afterCreate: function(item, options) { - // }, - // afterDestroy: function(user, options) { - // user.username = 'Toni' - // }, + 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) { - const Audit = sequelize.models.Audit + let {updateType, data_type} = options let auditOptions = returnAuditOptions(updateType,item, data_type) Audit.create(auditOptions[0], {success: true}) diff --git a/models/user.js b/models/user.js index 6dfa113..b573a8b 100644 --- a/models/user.js +++ b/models/user.js @@ -12,4 +12,4 @@ module.exports = function(sequelize, DataTypes) { } }); return User; -}; \ No newline at end of file +}; diff --git a/package.json b/package.json index 45a7591..1445ebe 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/routes/items.js b/routes/items.js index 3e86ea6..61e8244 100644 --- a/routes/items.js +++ b/routes/items.js @@ -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' ) @@ -19,12 +20,20 @@ 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 ) => { - response.render('items/weekly_review', {user: request.user}) + const {User, Audit, Item} = request.app.get('models') + + const user_id = request.user.id + // console.log('uid: ', request.user.id); + grabUserStats( User, user_id, Audit, Item) + .then( userStats => { + console.log('>>>>>>>>>', userStats) + response.render('items/weekly_review', {userStats}) + }) }) router.post( '/:id', ( request, response ) => { diff --git a/src/Auditor.js b/src/Auditor.js index 7ea59f3..f99aacb 100644 --- a/src/Auditor.js +++ b/src/Auditor.js @@ -1,7 +1,21 @@ const returnAuditOptions = (updateType, item, data_type) => { - console.log('returning Audit Options',updateType, data_type); + console.log('returning Audit Options', updateType, data_type); const auditOptions = updateType.map(type => { console.log('type',type, 'data_type', data_type); + if(type === 'create'){ + console.log('in 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 + } + console.log('>>>>>>',item); + return options + } if(type === 'completed'){ console.log('in completed'); let options = { diff --git a/src/weekly_report.js b/src/weekly_report.js new file mode 100644 index 0000000..85d47b1 --- /dev/null +++ b/src/weekly_report.js @@ -0,0 +1,68 @@ +const moment = require('moment') +const today = moment() +const todaysDate = moment() +const minusSevenDays = todaysDate.subtract(7, 'days') +console.log('-7: ', minusSevenDays.format("dddd, MMMM Do YYYY, h:mm:ss a"), '\n'); +console.log('todaysDate: ', today.format("dddd, MMMM Do YYYY, h:mm:ss a")); + + +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 + }) + console.log(); + 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) + console.log('raw Stats: ',created, changed, completed, total); + const userStats = {created, changed, completed, total} + console.log('userStats: ', userStats); + return userStats + }) + + return stats +} +const grabUserStats = (User, user_id, Audit, Item) => { + const where = {id: user_id} + const userStats = User.findOne({where}) + .then(user => { + return Math.abs(todaysDate.diff(user.createdAt, 'days')) + console.log('user: ', user); + }) + .then(lengthOfUse => { + console.log('lengthOfUse', lengthOfUse); + return calculateStats(Audit, user_id) + }) + + return userStats +} + +module.exports = grabUserStats diff --git a/views/items/weekly_review.pug b/views/items/weekly_review.pug index 971ed59..bfd05d3 100644 --- a/views/items/weekly_review.pug +++ b/views/items/weekly_review.pug @@ -1,5 +1,6 @@ -extends ../layouts/authenticated-layout block content h1 Your weekly review + for record in userStats + p=record a.btn.btn-success(href="/items") Go to items From 7798069f62223e3916f9d3d82ad1d3570f9ca278 Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Fri, 4 Nov 2016 11:51:37 -0700 Subject: [PATCH 11/12] refactored grabUserStats - broke out lengthOfUse and calculateStats functions --- src/weekly_report.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/weekly_report.js b/src/weekly_report.js index 85d47b1..83f3a32 100644 --- a/src/weekly_report.js +++ b/src/weekly_report.js @@ -5,6 +5,11 @@ const minusSevenDays = todaysDate.subtract(7, 'days') console.log('-7: ', minusSevenDays.format("dddd, MMMM Do YYYY, h:mm:ss a"), '\n'); console.log('todaysDate: ', today.format("dddd, MMMM Do YYYY, h:mm:ss a")); +const lengthOfUse = (User, where) => + User.findOne({where}) + .then(user => { + return Math.abs(todaysDate.diff(user.createdAt, 'days')) + }) const bulletsCreated = (auditRecords) => { const createdThisWeek = auditRecords.filter(record => record.createdAt >= minusSevenDays) @@ -52,16 +57,8 @@ const calculateStats = (Audit, user_id) => { } const grabUserStats = (User, user_id, Audit, Item) => { const where = {id: user_id} - const userStats = User.findOne({where}) - .then(user => { - return Math.abs(todaysDate.diff(user.createdAt, 'days')) - console.log('user: ', user); - }) - .then(lengthOfUse => { - console.log('lengthOfUse', lengthOfUse); - return calculateStats(Audit, user_id) - }) - + const userStats = calculateStats(Audit, user_id) + userStats.lengthOfUse = lengthOfUse(User, where) return userStats } From d0744e11bf4a23a89e04921bca670ed4d0b42e54 Mon Sep 17 00:00:00 2001 From: John Hopkins Date: Fri, 4 Nov 2016 13:33:52 -0700 Subject: [PATCH 12/12] weekly report mostly working --- routes/items.js | 14 +++++++------- src/Auditor.js | 13 ++----------- src/weekly_report.js | 16 +++++++--------- views/items/weekly_review.pug | 10 ++++++++-- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/routes/items.js b/routes/items.js index 61e8244..913027f 100644 --- a/routes/items.js +++ b/routes/items.js @@ -26,14 +26,14 @@ router.post( '/', ( request, response ) => { router.get( '/weekly', ( request, response ) => { const {User, Audit, Item} = request.app.get('models') - - const user_id = request.user.id + const user = request.user + const user_id = user.id // console.log('uid: ', request.user.id); grabUserStats( User, user_id, Audit, Item) - .then( userStats => { - console.log('>>>>>>>>>', userStats) - response.render('items/weekly_review', {userStats}) - }) + .then( userStats => { + let keys = Object.keys(userStats) + response.render('items/weekly_review', {userStats, user, keys}) + }) }) router.post( '/:id', ( request, response ) => { @@ -42,7 +42,7 @@ router.post( '/:id', ( request, response ) => { const where = { id, user_id: request.user.id } const valid_params = Item.filterParameters( request.body ) const fields = Object.keys(valid_params) - let data_type_string = `Item.tableAttributes.${fields}.type.constructor.key` + const data_type_string = `Item.tableAttributes.${fields}.type.constructor.key` const data_type = eval(data_type_string) diff --git a/src/Auditor.js b/src/Auditor.js index f99aacb..65aee3b 100644 --- a/src/Auditor.js +++ b/src/Auditor.js @@ -1,9 +1,7 @@ const returnAuditOptions = (updateType, item, data_type) => { - console.log('returning Audit Options', updateType, data_type); + const auditOptions = updateType.map(type => { - console.log('type',type, 'data_type', data_type); - if(type === 'create'){ - console.log('in create'); + if(type === 'create'){ let options = { table_name: 'Items', element_id: item.id, @@ -13,11 +11,9 @@ const returnAuditOptions = (updateType, item, data_type) => { field_type: data_type, user_id: item.user_id } - console.log('>>>>>>',item); return options } if(type === 'completed'){ - console.log('in completed'); let options = { table_name: 'Items', element_id: item.id, @@ -27,12 +23,10 @@ const returnAuditOptions = (updateType, item, data_type) => { field_type: data_type, user_id: item.user_id } - console.log('>>>>>>',item._previousDataValues.title); return options } if(type === 'title' ){ - console.log('type: ', item._previousDataValues.title ); let options = { table_name: 'Items', element_id: item.id, @@ -42,7 +36,6 @@ const returnAuditOptions = (updateType, item, data_type) => { field_type: data_type, user_id: item.user_id } - console.log('title: ',options); return options } @@ -56,11 +49,9 @@ const returnAuditOptions = (updateType, item, data_type) => { field_type: data_type, user_id: item.user_id } - console.log('description', options); return options } }) - console.log('auditOptions',auditOptions); return auditOptions } diff --git a/src/weekly_report.js b/src/weekly_report.js index 83f3a32..a77b39b 100644 --- a/src/weekly_report.js +++ b/src/weekly_report.js @@ -2,14 +2,14 @@ const moment = require('moment') const today = moment() const todaysDate = moment() const minusSevenDays = todaysDate.subtract(7, 'days') -console.log('-7: ', minusSevenDays.format("dddd, MMMM Do YYYY, h:mm:ss a"), '\n'); -console.log('todaysDate: ', today.format("dddd, MMMM Do YYYY, h:mm:ss a")); -const lengthOfUse = (User, where) => - User.findOne({where}) +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) @@ -36,20 +36,17 @@ const bulletsCompleted = (auditRecords) => { record.new_value == true && record.createdAt >= minusSevenDays }) - console.log(); return completedItems.length } const calculateStats = (Audit, user_id) => { - const stats =Audit.findAll({where: {user_id: 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) - console.log('raw Stats: ',created, changed, completed, total); const userStats = {created, changed, completed, total} - console.log('userStats: ', userStats); return userStats }) @@ -58,7 +55,8 @@ const calculateStats = (Audit, user_id) => { const grabUserStats = (User, user_id, Audit, Item) => { const where = {id: user_id} const userStats = calculateStats(Audit, user_id) - userStats.lengthOfUse = lengthOfUse(User, where) + const duration = Promise.resolve(lengthOfUse(User, where)).then(result => result) + userStats.duration = duration return userStats } diff --git a/views/items/weekly_review.pug b/views/items/weekly_review.pug index bfd05d3..e6a3813 100644 --- a/views/items/weekly_review.pug +++ b/views/items/weekly_review.pug @@ -1,6 +1,12 @@ +extends ../layouts/authenticated-layout block content h1 Your weekly review - for record in userStats - p=record + + 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