diff --git a/app/controllers/articles.js b/app/controllers/articles.js index dfa90af..6db520e 100644 --- a/app/controllers/articles.js +++ b/app/controllers/articles.js @@ -7,7 +7,8 @@ var mongoose = require('mongoose') var Article = mongoose.model('Article') var utils = require('../../lib/utils') var extend = require('util')._extend - +var geocoder = require('node-geocoder')('google', 'http', null) +var async = require('async') /** * Load */ @@ -30,116 +31,167 @@ exports.load = function (req, res, next, id){ exports.index = function (req, res){ var page = (req.params.page > 0 ? req.params.page : 1) - 1; var perPage = 30; - var options = { - perPage: perPage, - page: page - }; + perPage: perPage, + page: page, + filters: {} + }; + req.query.title ? options.filters.title = {'$regex': req.query.title} : ""; + req.query.body ? options.filters.body = {'$regex': req.query.body} : ""; + req.query.minPrice ? options.filters.price = {'$gte' : req.query.minPrice } : ""; + req.query.maxPrice ? (options.filters.price ) ? options.filters.price = {'$gte' : req.query.minPrice, '$lte' : req.query.maxPrice } : options.filters.price = {'$lte' : req.query.maxPrice } : ""; + + async.waterfall([ + function(callback) { + if (req.query.country && req.query.city){ + codify(req.query.city+", "+req.query.country, function(err, res){ + if(!err){ + req.query.criteria = JSON.stringify({"lon": res[0].longitude, "lat": res[0].latitude, "distance": "500" }); + } + callback(null) + }) + } + else if(req.query.city){ + codify(req.query.city, function(err, res){ + if(!err){ + req.query.criteria = JSON.stringify({"lon": res[0].longitude, "lat": res[0].latitude, "distance": "500" }); + } + callback(null) + }) + } + else if(req.query.country){ + codify(req.query.country, function(err, res){ + if(!err){ + req.query.criteria = JSON.stringify({"lon": res[0].longitude, "lat": res[0].latitude, "distance": "500" }); + } + callback(null) + }) + } + else{ + callback(null) + } + }, + function(callback) { - if(req.query.criteria){ + if(req.query.criteria){ - try{ - var criteria= JSON.parse(req.query.criteria); - options.criteria=[]; - var count = 0; - var isGeo=false; + try{ + var criteria= JSON.parse(req.query.criteria); + options.criteria=[]; + var count = 0; + var isGeo=false; - var notRegexing = false; - for(i in criteria){ + var notRegexing = false; + for(i in criteria){ - //check for geolocational query by finding a lat param - if(criteria.lat){ - options.criteria={}; - try{ + //check for geolocational query by finding a lat param + if(criteria.lat){ + options.criteria={}; + try{ - criteria['geo']=true; - criteria['lat'] = parseFloat(criteria['lat']) - criteria['lon'] = parseFloat(criteria['lon']) - criteria['distance'] = parseFloat(criteria['distance']) - - isGeo=true; + criteria['geo']=true; + criteria['lat'] = parseFloat(criteria['lat']) + criteria['lon'] = parseFloat(criteria['lon']) + criteria['distance'] = parseFloat(criteria['distance']) - if(criteria['query']){ - criteria['query']=criteria['query']; - for(t in criteria['query']){ - if(notRegexing==false){ - criteria['query'][t] = new RegExp(".*?"+criteria['query'][t]+".*?", 'i') + isGeo=true; + + if(criteria['query']){ + criteria['query']=criteria['query']; + for(t in criteria['query']){ + if(notRegexing==false){ + criteria['query'][t] = new RegExp(".*?"+criteria['query'][t]+".*?", 'i') + } + + notRegexing=true; + } } - - notRegexing=true; + + else{ + criteria['query']={}; + } + + } + + catch(err){ + callback('geospatial query failed because the distance,lon, lat not working to parseFloat'); + console.log('geospatial query failed because the distance,lon, lat not working to parseFloat') } } + options.criteria[count]={}; + if(isGeo==false){ + if(isNaN(criteria[i]) == true){ + options.criteria[count][i]=new RegExp(".*?"+criteria[i]+".*?", 'i') + } + + else{ + options.criteria[count][i]= criteria[i]; + } + + + + count = count+1; + } else{ - criteria['query']={}; + + options.criteria= criteria; } } - catch(err){ - console.log('geospatial query failed because the distance,lon, lat not working to parseFloat') - } - } - options.criteria[count]={}; - if(isGeo==false){ - if(isNaN(criteria[i]) == true){ - options.criteria[count][i]=new RegExp(".*?"+criteria[i]+".*?", 'i') - } + console.log(options.criteria) - else{ - options.criteria[count][i]= criteria[i]; - } - - + callback(null); + } - count = count+1; + catch(err){ + callback('not searching by critera as no conditions are specified in array formation / e.g. {title:"example"}'); + console.log(err); + console.log('not searching by critera as no conditions are specified in array formation / e.g. {title:"example"}') } - else{ - options.criteria= criteria; - } } - - console.log(options.criteria) - } + else{ + callback(null); + } - catch(err){ - console.log(err); - console.log('not searching by critera as no conditions are specified in array formation / e.g. {title:"example"}') + } + ], function (err) { + if(err){ + res.status(500).send(err); + } + else{ + if(req.query.format=="json"){ + Article.list(options, function (err, articles) { + if (err) return res.render('500'); + Article.count().exec(function (err, count) { + res.send( { + title: 'Articles', + articles: articles, + page: page + 1, + pages: Math.ceil(count / perPage) + }); + }); + }); + } + else { + Article.list(options, function (err, articles) { + if (err) return res.render('500'); + Article.count().exec(function (err, count) { + res.render('articles/index', { + title: 'Articles', + articles: articles, + page: page + 1, + pages: Math.ceil(count / perPage) + }); + }); + }); + } } - - } - - - if(req.query.format=="json"){ - Article.list(options, function (err, articles) { - if (err) return res.render('500'); - Article.count().exec(function (err, count) { - res.send( { - title: 'Articles', - articles: articles, - page: page + 1, - pages: Math.ceil(count / perPage) - }); - }); - }); - } - else{ - Article.list(options, function (err, articles) { - if (err) return res.render('500'); - Article.count().exec(function (err, count) { - res.render('articles/index', { - title: 'Articles', - articles: articles, - page: page + 1, - pages: Math.ceil(count / perPage) - }); - }); }); - - } }; @@ -152,9 +204,9 @@ exports.list = function (req, res){ var perPage = 30; var options = { - perPage: perPage, - page: page - }; + perPage: perPage, + page: page + }; if(req.query.criteria){ @@ -177,16 +229,16 @@ exports.list = function (req, res){ criteria['lat'] = parseFloat(criteria['lat']) criteria['lon'] = parseFloat(criteria['lon']) criteria['distance'] = parseFloat(criteria['distance']) - + isGeo=true; if(criteria['query']){ criteria['query']=criteria['query']; for(t in criteria['query']){ if(notRegexing==false){ - criteria['query'][t] = new RegExp(".*?"+criteria['query'][t]+".*?", 'i') + criteria['query'][t] = new RegExp(".*?"+criteria['query'][t]+".*?", 'i') } - + notRegexing=true; } } @@ -203,14 +255,14 @@ exports.list = function (req, res){ options.criteria[count]={}; if(isGeo==false){ if(isNaN(criteria[i]) == true){ - options.criteria[count][i]=new RegExp(".*?"+criteria[i]+".*?", 'i') + options.criteria[count][i]=new RegExp(".*?"+criteria[i]+".*?", 'i') } else{ - options.criteria[count][i]= criteria[i]; + options.criteria[count][i]= criteria[i]; } - - + + count = count+1; } @@ -220,7 +272,7 @@ exports.list = function (req, res){ options.criteria= criteria; } } - + console.log(options.criteria) } @@ -231,33 +283,33 @@ exports.list = function (req, res){ } - - + + if(req.query.format=="json"){ Article.list(options, function (err, articles) { - if (err) return res.render('500'); - Article.count().exec(function (err, count) { - res.send( { - title: 'Articles', - articles: articles, - page: page + 1, - pages: Math.ceil(count / perPage) + if (err) return res.render('500'); + Article.count().exec(function (err, count) { + res.send( { + title: 'Articles', + articles: articles, + page: page + 1, + pages: Math.ceil(count / perPage) + }); }); }); - }); } else{ - Article.list(options, function (err, articles) { - if (err) return res.render('500'); - Article.count().exec(function (err, count) { - res.render('articles/list', { - title: 'Articles', - articles: articles, - page: page + 1, - pages: Math.ceil(count / perPage) + Article.list(options, function (err, articles) { + if (err) return res.render('500'); + Article.count().exec(function (err, count) { + res.render('articles/list', { + title: 'Articles', + articles: articles, + page: page + 1, + pages: Math.ceil(count / perPage) + }); }); }); - }); } }; @@ -292,40 +344,40 @@ exports.new = function (req, res){ exports.create = function (req, res) { var article = new Article(req.body); var images = req.files.image - ? [req.files.image] - : undefined; + ? [req.files.image] + : undefined; article.user = req.user; - if(req.query.format=="json"){ - article.uploadAndSave(images, function (err) { - if (!err) { - req.flash('success', 'Successfully created article!'); - return res.redirect('/articles/'+article._id); - } - res.send({ - title: 'New Article', - article: article, - errors: utils.errors(err.errors || err) - }); + if(req.query.format=="json"){ + article.uploadAndSave(images, function (err) { + if (!err) { + req.flash('success', 'Successfully created article!'); + return res.redirect('/articles/'+article._id); + } + res.send({ + title: 'New Article', + article: article, + errors: utils.errors(err.errors || err) }); + }); - } - - else{ + } - article.uploadAndSave(images, function (err) { - if (!err) { - req.flash('success', 'Successfully created article!'); - return res.redirect('/articles/'+article._id); - } - res.render('articles/new', { - title: 'New Article', - article: article, - errors: utils.errors(err.errors || err) - }); + else{ + + article.uploadAndSave(images, function (err) { + if (!err) { + req.flash('success', 'Successfully created article!'); + return res.redirect('/articles/'+article._id); + } + res.render('articles/new', { + title: 'New Article', + article: article, + errors: utils.errors(err.errors || err) }); - } + }); + } }; /** @@ -334,14 +386,14 @@ exports.create = function (req, res) { exports.edit = function (req, res) { - if(req.query.format=="json"){ + if(req.query.format=="json"){ res.send( { title: 'Edit ' + req.article.title, article: req.article }); - } + } - else{ + else{ res.render('articles/edit', { title: 'Edit ' + req.article.title, article: req.article @@ -356,8 +408,8 @@ exports.edit = function (req, res) { exports.update = function (req, res){ var article = req.article; var images = req.files.image - ? [req.files.image] - : undefined; + ? [req.files.image] + : undefined; // make sure no one changes the user delete req.body.user; @@ -375,7 +427,7 @@ exports.update = function (req, res){ } if(req.query.format=="json"){ - res.send( { + res.send( { title: 'Edit Article', article: article, errors: utils.errors(err.errors || err) @@ -398,7 +450,7 @@ exports.update = function (req, res){ */ exports.show = function (req, res){ - + if(req.query.format=="json"){ res.send( { @@ -434,3 +486,12 @@ exports.destroy = function (req, res){ } }); }; + + +var codify = function(address, cb){ + geocoder.geocode({address: address}).then(function(res) { + cb(null, res) + }).catch(function(err){ + cb(err, null) + }); +} \ No newline at end of file diff --git a/app/models/article.js b/app/models/article.js index d698f69..8e8ac34 100644 --- a/app/models/article.js +++ b/app/models/article.js @@ -19,7 +19,7 @@ var Schema = mongoose.Schema; */ var getTags = function (tags) { - return tags.join(','); + return tags.join(','); }; /** @@ -27,7 +27,7 @@ var getTags = function (tags) { */ var setTags = function (tags) { - return tags.split(','); + return tags.split(','); }; /** @@ -35,60 +35,60 @@ var setTags = function (tags) { */ var ArticleSchema = new Schema({ - title: {type : String, default : '', trim : true}, - body: {type : String, default : '', trim : true}, - user: {type : Schema.ObjectId, ref : 'User'}, - comments: [{ - body: { type : String, default : '' }, - user: { type : Schema.ObjectId, ref : 'User' }, - createdAt: { type : Date, default : Date.now } - }], - ratings: [{ - rating: { type : Number, default : 3 }, - user: { type : Schema.ObjectId, ref : 'User' }, - createdAt: { type : Date, default : Date.now } - }], - - likes: [{ - user: { type : Schema.ObjectId, ref : 'User' }, - createdAt: { type : Date, default : Date.now } - }], - - categories: [{ - category: { type :String, default :'default'}, - user: { type : Schema.ObjectId, ref : 'User' }, - createdAt: { type : Date, default : Date.now } - }], - - tags: {type: [], get: getTags, set: setTags}, - image: { - cdnUri: String, - files: [] - }, - createdAt : {type : Date, default : Date.now}, - - //added - media: [{ - url: { type : String, default : '' }, - type: { type : String, default : '' }, - files: [], - createdAt: { type : Date, default : Date.now } - }], - location: {type: [Number], default: [-74.0059, 40.7127], index: '2dsphere' }, - //loc:{ type: {type : String, default : 'Point', index:true}, coordinates: {type: [Number], default: [-74.0059, 40.7127], index: '2dsphere' }}, - - //type: String, default : 'Point' - type: {type : String, default : 'Point', index:true}, - updatedAt : {type : Date, default : Date.now}, - price:{type: Number, default:0.00}, - rating:{type: Number, default:0.00}, - numRatings:{type: Number, default:0}, - email: {type : String, default : '', index:true}, - startDate: { type : Date, default : Date.now }, - endDate: { type : Date }, - availableNow: { type : Boolean, default:false }, - availabilitySlots: {type: []}, - accessSecret:{type : String, default : ''} + title: {type : String, default : '', trim : true}, + body: {type : String, default : '', trim : true}, + user: {type : Schema.ObjectId, ref : 'User'}, + comments: [{ + body: { type : String, default : '' }, + user: { type : Schema.ObjectId, ref : 'User' }, + createdAt: { type : Date, default : Date.now } + }], + ratings: [{ + rating: { type : Number, default : 3 }, + user: { type : Schema.ObjectId, ref : 'User' }, + createdAt: { type : Date, default : Date.now } + }], + + likes: [{ + user: { type : Schema.ObjectId, ref : 'User' }, + createdAt: { type : Date, default : Date.now } + }], + + categories: [{ + category: { type :String, default :'default'}, + user: { type : Schema.ObjectId, ref : 'User' }, + createdAt: { type : Date, default : Date.now } + }], + + tags: {type: [], get: getTags, set: setTags}, + image: { + cdnUri: String, + files: [] + }, + createdAt : {type : Date, default : Date.now}, + + //added + media: [{ + url: { type : String, default : '' }, + type: { type : String, default : '' }, + files: [], + createdAt: { type : Date, default : Date.now } + }], + location: {type: [Number], default: [-74.0059, 40.7127], index: '2dsphere' }, + //loc:{ type: {type : String, default : 'Point', index:true}, coordinates: {type: [Number], default: [-74.0059, 40.7127], index: '2dsphere' }}, + + //type: String, default : 'Point' + type: {type : String, default : 'Point', index:true}, + updatedAt : {type : Date, default : Date.now}, + price:{type: Number, default:0.00}, + rating:{type: Number, default:0.00}, + numRatings:{type: Number, default:0}, + email: {type : String, default : '', index:true}, + startDate: { type : Date, default : Date.now }, + endDate: { type : Date }, + availableNow: { type : Boolean, default:false }, + availabilitySlots: {type: []}, + accessSecret:{type : String, default : ''} }); @@ -111,16 +111,16 @@ ArticleSchema.path('body').required(true, 'Article body cannot be blank'); */ ArticleSchema.pre('remove', function (next) { - /* - var imager = new Imager(imagerConfig, 'S3'); - var files = this.image.files; - - // if there are files associated with the item, remove from the cloud too - imager.remove(files, function (err) { - if (err) return next(err); - }, 'article'); -*/ - next(); + /* + var imager = new Imager(imagerConfig, 'S3'); + var files = this.image.files; + + // if there are files associated with the item, remove from the cloud too + imager.remove(files, function (err) { + if (err) return next(err); + }, 'article'); + */ + next(); }); /** @@ -129,115 +129,115 @@ ArticleSchema.pre('remove', function (next) { ArticleSchema.methods = { - /** - * Save article and upload image - * - * @param {Object} images - * @param {Function} cb - * @api private - */ - - uploadAndSave: function (images, cb) { - if (!images || !images.length) return this.save(cb) - - console.log(images); - var fs = require('fs'); - //create uploads folder if it doesn't exsit - try{ - - var statsFolder = fs.lstatSync('./public/uploads/'); - fs.createReadStream(images[0]['path']).pipe(fs.createWriteStream('./public/uploads/'+images[0]['name'])) - - } - catch(err){ - console.log('uploads Folder doesnt exist. create /public/uploads folder'); - - fs.mkdir('./public/uploads/',function(e){ - - console.log('created uploads folder') - fs.createReadStream(images[0]['path']).pipe(fs.createWriteStream('./public/uploads/'+images[0]['name'])) - }); - } - - - - console.log('save upload') - ; - - //if using amazon... - //var imager = new Imager(imagerConfig, 'S3'); - var self = this; - - this.validate(function (err) { - if (err) { - console.log("error:"+err); - return cb(err); - - } - - - if (images.length) { - self.image = { cdnUri : '/uploads/'+images[0]['name'], files : images }; + /** + * Save article and upload image + * + * @param {Object} images + * @param {Function} cb + * @api private + */ + + uploadAndSave: function (images, cb) { + if (!images || !images.length) return this.save(cb) + + console.log(images); + var fs = require('fs'); + //create uploads folder if it doesn't exsit + try{ + + var statsFolder = fs.lstatSync('./public/uploads/'); + fs.createReadStream(images[0]['path']).pipe(fs.createWriteStream('./public/uploads/'+images[0]['name'])) + } - self.save(cb); - - - /* - imager.upload(images, function (err, cdnUri, files) { - if (err) { - console.log("error1:"+err); - return cb(err); - - } - if (files.length) { - self.image = { cdnUri : cdnUri, files : files }; + catch(err){ + console.log('uploads Folder doesnt exist. create /public/uploads folder'); + + fs.mkdir('./public/uploads/',function(e){ + + console.log('created uploads folder') + fs.createReadStream(images[0]['path']).pipe(fs.createWriteStream('./public/uploads/'+images[0]['name'])) + }); } - self.save(cb); - }, 'article');*/ - }); - }, - - /** - * Add comment - * - * @param {User} user - * @param {Object} comment - * @param {Function} cb - * @api private - */ - - addComment: function (user, comment, cb) { - // var notify = require('../mailer'); - - this.comments.push({ - body: comment.body, - user: user._id - }); -/* - if (!this.user.email) this.user.email = 'email@product.com'; - notify.comment({ - article: this, - currentUser: user, - comment: comment.body - }); -*/ - this.save(cb); - }, - - /** - * Remove comment - * - * @param {commentId} String - * @param {Function} cb - * @api private - */ - - removeComment: function (commentId, cb) { - var index = utils.indexof(this.comments, { id: commentId }); - if (~index) this.comments.splice(index, 1); - else return cb('not found'); - this.save(cb); - }, + + + + console.log('save upload') + ; + + //if using amazon... + //var imager = new Imager(imagerConfig, 'S3'); + var self = this; + + this.validate(function (err) { + if (err) { + console.log("error:"+err); + return cb(err); + + } + + + if (images.length) { + self.image = { cdnUri : '/uploads/'+images[0]['name'], files : images }; + } + self.save(cb); + + + /* + imager.upload(images, function (err, cdnUri, files) { + if (err) { + console.log("error1:"+err); + return cb(err); + + } + if (files.length) { + self.image = { cdnUri : cdnUri, files : files }; + } + self.save(cb); + }, 'article');*/ + }); + }, + + /** + * Add comment + * + * @param {User} user + * @param {Object} comment + * @param {Function} cb + * @api private + */ + + addComment: function (user, comment, cb) { + // var notify = require('../mailer'); + + this.comments.push({ + body: comment.body, + user: user._id + }); + /* + if (!this.user.email) this.user.email = 'email@product.com'; + notify.comment({ + article: this, + currentUser: user, + comment: comment.body + }); + */ + this.save(cb); + }, + + /** + * Remove comment + * + * @param {commentId} String + * @param {Function} cb + * @api private + */ + + removeComment: function (commentId, cb) { + var index = utils.indexof(this.comments, { id: commentId }); + if (~index) this.comments.splice(index, 1); + else return cb('not found'); + this.save(cb); + }, @@ -249,85 +249,85 @@ ArticleSchema.methods = { - addRating: function (user, comment, cb) { - // var notify = require('../mailer'); + addRating: function (user, comment, cb) { + // var notify = require('../mailer'); - this.ratings.push({ - rating: ratings.rating, - user: user._id - }) - this.save(cb); - }, + this.ratings.push({ + rating: ratings.rating, + user: user._id + }) + this.save(cb); + }, - /** - * Remove like - * - * @param {commentId} String - * @param {Function} cb - * @api private - */ + /** + * Remove like + * + * @param {commentId} String + * @param {Function} cb + * @api private + */ - removeRating: function (commentId, cb) { - var index = utils.indexof(this.likes, { id: commentId }); - if (~index) this.likes.splice(index, 1); - else return cb('not found'); - this.save(cb); - }, + removeRating: function (commentId, cb) { + var index = utils.indexof(this.likes, { id: commentId }); + if (~index) this.likes.splice(index, 1); + else return cb('not found'); + this.save(cb); + }, - addLike: function (user, comment, cb) { - // var notify = require('../mailer'); + addLike: function (user, comment, cb) { + // var notify = require('../mailer'); - this.likes.push({ - user: user._id - }) - this.save(cb); - }, + this.likes.push({ + user: user._id + }) + this.save(cb); + }, - /** - * Remove like - * - * @param {commentId} String - * @param {Function} cb - * @api private - */ + /** + * Remove like + * + * @param {commentId} String + * @param {Function} cb + * @api private + */ - removeLike: function (commentId, cb) { - var index = utils.indexof(this.likes, { id: commentId }); - if (~index) this.likes.splice(index, 1); - else return cb('not found'); - this.save(cb); - }, + removeLike: function (commentId, cb) { + var index = utils.indexof(this.likes, { id: commentId }); + if (~index) this.likes.splice(index, 1); + else return cb('not found'); + this.save(cb); + }, - addCategory: function (user, comment, cb) { - // var notify = require('../mailer'); + addCategory: function (user, comment, cb) { + // var notify = require('../mailer'); - this.categories.push({ - category: comment.category, - user: user._id - }) - this.save(cb); - }, + this.categories.push({ + category: comment.category, + user: user._id + }) + this.save(cb); + }, - /** - * Remove like - * - * @param {commentId} String - * @param {Function} cb - * @api private - */ + /** + * Remove like + * + * @param {commentId} String + * @param {Function} cb + * @api private + */ - removeCategory: function (commentId, cb) { - var index = utils.indexof(this.categories, { id: commentId }); - if (~index) this.categories.splice(index, 1); - else return cb('not found'); - this.save(cb); - } + removeCategory: function (commentId, cb) { + var index = utils.indexof(this.categories, { id: commentId }); + if (~index) this.categories.splice(index, 1); + else return cb('not found'); + this.save(cb); + } } @@ -341,66 +341,67 @@ ArticleSchema.methods = { ArticleSchema.statics = { - /** - * Find article by id - * - * @param {ObjectId} id - * @param {Function} cb - * @api private - */ - - load: function (id, cb) { - this.findOne({ _id : id }) - .populate('user', 'name email username') - .populate('comments.user') - .exec(cb); - }, - - /** - * List articles - * - * @param {Object} options - * @param {Function} cb - * @api private - */ - - list: function (options, cb) { - - //area1 = { center: [-74.0059, 40.7127], radius: 5000000000, unique: true } - var criteria = options.criteria || {} - // this.find({location:{$near:[-74.0059, 40.7127], $maxDistance:500000000}}) - if(criteria['lon']){ - console.log(criteria['lon']); - this.find() - .or(criteria['query']) - .where('location').near({ - center: {'coordinates':[criteria['lon'], criteria['lat']], 'type':"Point"}, - maxDistance: criteria['distance'], - spherical: true - }) - - .populate('user', 'name username') - .sort({'createdAt': -1}) // sort by date - .limit(options.perPage) - .skip(options.perPage * options.page) - .exec(cb); - } - - else{ - console.log('not geospatial') - - this.find() - .or(criteria) - .populate('user', 'name username') - .sort({'createdAt': -1}) // sort by date - .limit(options.perPage) - .skip(options.perPage * options.page) - .exec(cb); - - - } - - } + /** + * Find article by id + * + * @param {ObjectId} id + * @param {Function} cb + * @api private + */ + + load: function (id, cb) { + this.findOne({ _id : id }) + .populate('user', 'name email username') + .populate('comments.user') + .exec(cb); + }, + + /** + * List articles + * + * @param {Object} options + * @param {Function} cb + * @api private + */ + + list: function (options, cb) { + + //area1 = { center: [-74.0059, 40.7127], radius: 5000000000, unique: true } + var criteria = options.criteria || {} + var filters = options.filters; + // this.find({location:{$near:[-74.0059, 40.7127], $maxDistance:500000000}}) + if(criteria['lon']){ + console.log(criteria['lon']); + this.find(filters) + .or(criteria['query']) + .where('location').near({ + center: {'coordinates':[criteria['lon'], criteria['lat']], 'type':"Point"}, + maxDistance: criteria['distance'], + spherical: true + }) + + .populate('user', 'name username') + .sort({'createdAt': -1}) // sort by date + .limit(options.perPage) + .skip(options.perPage * options.page) + .exec(cb); + } + + else{ + console.log('not geospatial') + + this.find(filters) + .or(criteria) + .populate('user', 'name username') + .sort({'createdAt': -1}) // sort by date + .limit(options.perPage) + .skip(options.perPage * options.page) + .exec(cb); + + + } + + } } mongoose.model('Article', ArticleSchema); diff --git a/package.json b/package.json index 911a348..9ef2b55 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,9 @@ "view-helpers": "0.1.5", "winston": "1.0.1", "emailjs": "", - "ncp": "" + "ncp": "", + "node-geocoder": "3.5.1", + "chai": "~3.4.1" }, "devDependencies": { "exposify": "^0.5.0", diff --git a/test/test-articles-search.js b/test/test-articles-search.js new file mode 100644 index 0000000..cb10431 --- /dev/null +++ b/test/test-articles-search.js @@ -0,0 +1,202 @@ + +var expect = require('chai').expect, + supertest = require('supertest'), + api = supertest.agent("http://localhost:8080") + + +// ******************************************************** +// STEP 1: . +// expected result 302 bad request +// status pass +// ******************************************************** +it('STEP 1: Create a test user', function (done) { + api.post('/users') + .send({ + email: 'foobar@example.com', + name: 'Foo bar', + username: 'foobar', + password: 'foobar' + }) + .end(function(err, res) { + expect(res.status).to.be.equal(200); + done(); + }); +}); + +// ******************************************************** +// STEP 2: Login with the user . +// expected result 200 bad request +// status pass +// ******************************************************** +it("STEP 2: Login with the test user", function (done) { + api.post('/users/session') + .send({ + email: 'foobar@example.com', + password: 'foobar' + }) + .end(function(err, res) { + expect(res.status).to.be.equal(302); + done(); + }); +}); + +// ******************************************************** +// STEP 2.2: Create article +// expected result 200 +// status pass +// ******************************************************** +it("STEP 2.2: Create an article", function (done) { + api.post('/articles') + .send({ + title: 'test article', + body: 'This is a test Body' + }) + .end(function (err, res) { + expect(res.status).to.be.equal(302); + done(); + }); +}); + +// ******************************************************** +// STEP 3: Making a search article request with valid title. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 3: Making a search article request with valid title", function (done) { + api.get('/articles?format=json&title=test') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.status).to.be.equal(200); + done(); + }); +}); + +// ******************************************************** +// STEP 3.1: Making a search article request with invalid title. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 3.1: Making a search article request with invalid title", function (done) { + api.get('/articles?format=json&title=blahblah') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.equal(0); + done(); + }); +}); + + +// ******************************************************** +// STEP 3.2: Making a search article request with valid body. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 3.2: Making a search article request with valid body", function (done) { + api.get('/articles?format=json&title=body') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.status).to.be.equal(200); + done(); + }); +}); + +// ******************************************************** +// STEP 3.3: Making a search article request with valid body. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 3.3: Making a search article request with invalid body", function (done) { + api.get('/articles?format=json&title=very fat body') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.equal(0); + done(); + }); +}); + + +// ******************************************************** +// STEP 4: Searching with default lat and long. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 4: Searching with default lat and long", function (done) { + api.get('/articles?format=json&criteria={"lon": "-74.0058999999999969", "lat": "40.7126999999999981", "distance": "500"}') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.above(0); + done(); + }); +}); + +// ******************************************************** +// STEP 4.1: Searching with non default lat and long. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 4.1: Searching with non default lat and long", function (done) { + api.get('/articles?format=json&criteria={"lon": "-74", "lat": "40", "distance": "50"}') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.equal(0); + done(); + }); +}); + +// ******************************************************** +// STEP 4.2: Searching with lat, long, title and body. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 4.2: Searching with lat, long, title and body", function (done) { + api.get('/articles?format=json&criteria={"lon": "-74", "lat": "40", "distance": "50"}&title=test&body=Body') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.equal(0); + done(); + }); +}); + + +// ******************************************************** +// STEP 4.3: Searching with default lat, long, title, body and price range. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 4.3: Searching with default lat, long, title and body", function (done) { + api.get('/articles?format=json&criteria={"lon": "-74.0058999999999969", "lat": "40.7126999999999981", "distance": "500"}&title=test&body=Body&minPrice=0&maxPrice=8') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.above(0); + done(); + }); +}); + +// ******************************************************** +// STEP 4.4: Searching with wrong lat, long, title, body and price range. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 4.4: Searching with wrong lat, long, title and body", function (done) { + api.get('/articles?format=json&criteria={"lon": "-74", "lat": "40", "distance": "50"}&title=test&body=body&minPrice=0&maxPrice=8') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.equal(0); + done(); + }); +}); + +// ******************************************************** +// STEP 4.5: Searching with city, country, title, body and price range. +// expected result 200 +// status pass +// ******************************************************** +it("STEP 4.5: Searching with lat, long, title and body", function (done) { + this.timeout(80000); + api.get('/articles?format=json&city=new york&country=usa&title=test&body=Body&minPrice=0&maxPrice=8') + .set('Accept', 'application/json') + .end(function (err, res) { + expect(res.body.articles.length).to.be.above(0); + done(); + }); +});