diff --git a/app/datasetParser.js b/app/datasetParser.js new file mode 100644 index 0000000..7238306 --- /dev/null +++ b/app/datasetParser.js @@ -0,0 +1,23 @@ +module.exports = { + uploadJSONtoFirebase: function (userID, datasetname, jsonData) { + //setup connecyion to fireabse + var firebase = require('firebase'); + + //Get a new static firebase reference key + let newDatasetKey = firebase.database().ref('datasets').push().key; + + let datasetDetails = { + name: datasetname, + userID: userID + }; + + //Upload the users data to firebase + var updates = {}; + updates['/datasets/' + newDatasetKey + '/data'] = jsonData; + updates['/datasets-metadata/'+newDatasetKey] = datasetDetails; + updates['/users/' + userID + '/datasets/' + newDatasetKey] = true; + + return firebase.database().ref().update(updates); + } +}; + diff --git a/app/routes.js b/app/routes.js index 86ba683..940ba47 100644 --- a/app/routes.js +++ b/app/routes.js @@ -1,31 +1,46 @@ const express = require('express'); -let multer = require('multer'); +let multer = require('multer'); +var upload = multer({dest: 'uploads'}); +const csv = require('csvtojson'); +var datasetParser = require('./datasetParser'); +var fs = require('fs'); + const path = require('path'); +let router = express.Router(); -let router = express.Router(); +router.post('/api/dataset', upload.any(), function (req, res, next) { + //Check if we have a userid associated with the file + if (req.body.userid) { + let userid = req.body.userid; + let dsName = req.body.datasetname; + let csvFilePath = req.files[0].path; -let storage = multer.diskStorage({ - destination: function (req, file, callback) { - callback(null, './uploads'); - }, - filename: function (req, file, callback) { - callback(null, file.fieldname + '-' + Date.now() + '.csv'); - } -}); + console.log(userid, dsName); -let upload = multer({storage: storage}).array('userDataset',1); + let csvData = []; -router.post('/api/dataset',function(req,res){ - upload(req,res,function(err) { - if(err) { - return res.end("Error uploading file."); - } - res.end("File is uploaded"); - }); + //Convert csv into json object + csv({checkType:true}).fromFile(csvFilePath).on('json', (jsonObj) => { + csvData.push(jsonObj); + }).on('done', (error) => { + //Once we have all the csv data as json upload to firabse + datasetParser.uploadJSONtoFirebase(userid,dsName,csvData); + + //Delete the uploaded file after the data is in firebase + fs.unlink(csvFilePath, function(err) { + if (err) { + return console.error(err); + } + res.sendStatus(200, "SUCCESS"); + }); + }); + } else { + res.end('Missing user id'); + } }); router.get('/', function (req, res) { - res.sendFile(path.join(__dirname,'../public/index.html')); + res.sendFile(path.join(__dirname, '../public/index.html')); }); router.get('/project', function (req, res) { @@ -36,4 +51,16 @@ router.get('/downloadGlobalTemplate', function (req, res) { res.download(path.join(__dirname, '../templates/GlobalCountiresTemplate.csv')); }); +router.get('/downloadUSCANTemplate', function (req, res) { + res.download(path.join(__dirname, '../templates/UnitedStatesCanadaTemplate.csv')); +}); + +router.get('/downloadUSATemplate', function (req, res) { + res.download(path.join(__dirname, '../templates/UnitedStatesTemplate.csv')); +}); + +router.get('/downloadCANTemplate', function (req, res) { + res.download(path.join(__dirname, '../templates/CanadaTemplate.csv')); +}); + module.exports = router; diff --git a/node_modules/mongoose/History.md b/node_modules/mongoose/History.md index 0c187c9..4a39472 100644 --- a/node_modules/mongoose/History.md +++ b/node_modules/mongoose/History.md @@ -1,3 +1,12 @@ +4.9.4 / 2017-04-09 +================== + * fix(schema): clone query middleware correctly #5153 #5141 [clozanosanchez](https://github.com/clozanosanchez) + * docs(aggregate): fix typo #5142 + * fix(query): cast .$ update to underlying array type #5130 + * fix(populate): don't mutate populate result in place #5128 + * fix(query): handle $setOnInsert consistent with $set #5126 + * docs(query): add strict mode option for findOneAndUpdate #5108 + 4.9.3 / 2017-04-02 ================== * docs: document.js fixes for functions prepended with `$` #5131 [krmannix](https://github.com/krmannix) diff --git a/node_modules/mongoose/lib/aggregate.js b/node_modules/mongoose/lib/aggregate.js index 8bb126b..623fbaa 100644 --- a/node_modules/mongoose/lib/aggregate.js +++ b/node_modules/mongoose/lib/aggregate.js @@ -171,7 +171,7 @@ Aggregate.prototype.project = function(arg) { * * ####Examples: * - * aggregate.match({ department: { $in: [ "sales", "engineering" } } }); + * aggregate.match({ department: { $in: [ "sales", "engineering" ] } }); * * @see $match http://docs.mongodb.org/manual/reference/aggregation/match/ * @method match diff --git a/node_modules/mongoose/lib/model.js b/node_modules/mongoose/lib/model.js index 01c8f70..493b2ce 100644 --- a/node_modules/mongoose/lib/model.js +++ b/node_modules/mongoose/lib/model.js @@ -1503,6 +1503,7 @@ Model.$where = function $where() { * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema. * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * * ####Examples: @@ -1616,6 +1617,8 @@ Model.findOneAndUpdate = function(conditions, update, options, callback) { * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/). * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * ####Examples: * @@ -1704,6 +1707,8 @@ Model.findByIdAndUpdate = function(id, update, options, callback) { * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0 * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * ####Examples: * @@ -1780,6 +1785,8 @@ Model.findOneAndRemove = function(conditions, options, callback) { * * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update * - `select`: sets the document fields to return + * - `passRawResult`: if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update * * ####Examples: * @@ -3055,10 +3062,11 @@ function populate(model, docs, options, callback) { if (Array.isArray(_val)) { var _valLength = _val.length; for (var j = 0; j < _valLength; ++j) { - if (_val[j] instanceof Document) { - _val[j] = _val[j]._id; + var __val = _val[j]; + if (__val instanceof Document) { + __val = __val._id; } - key = String(_val[j]); + key = String(__val); if (rawDocs[key]) { if (Array.isArray(rawDocs[key])) { rawDocs[key].push(val); diff --git a/node_modules/mongoose/lib/query.js b/node_modules/mongoose/lib/query.js index d8b1029..58c45f5 100644 --- a/node_modules/mongoose/lib/query.js +++ b/node_modules/mongoose/lib/query.js @@ -1779,6 +1779,8 @@ function prepareDiscriminatorCriteria(query) { * @param {Object|Query} [query] * @param {Object} [doc] * @param {Object} [options] + * @param {Boolean} [options.passRawResult] if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) * @param {Function} [callback] optional params are (error, doc), _unless_ `passRawResult` is used, in which case params are (error, doc, writeOpResult) * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult @@ -1888,6 +1890,8 @@ Query.prototype._findOneAndUpdate = function(callback) { * @memberOf Query * @param {Object} [conditions] * @param {Object} [options] + * @param {Boolean} [options.passRawResult] if true, passes the [raw result from the MongoDB driver as the third callback parameter](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify) + * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) * @param {Function} [callback] optional params are (error, document) * @return {Query} this * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command diff --git a/node_modules/mongoose/lib/schema.js b/node_modules/mongoose/lib/schema.js index 27b97a9..9087610 100644 --- a/node_modules/mongoose/lib/schema.js +++ b/node_modules/mongoose/lib/schema.js @@ -348,6 +348,7 @@ Schema.prototype.clone = function() { s.callQueue = this.callQueue.map(function(f) { return f; }); s.methods = utils.clone(this.methods); s.statics = utils.clone(this.statics); + s.s.hooks = this.s.hooks.clone(); return s; }; @@ -1705,6 +1706,10 @@ Schema.prototype._getSchema = function(path) { if (p !== parts.length && foundschema.schema) { var ret; if (parts[p] === '$') { + if (p + 1 === parts.length) { + // comments.$ + return foundschema; + } // comments.$.comments.$.title ret = search(parts.slice(p + 1), foundschema.schema); if (ret) { diff --git a/node_modules/mongoose/lib/services/query/castUpdate.js b/node_modules/mongoose/lib/services/query/castUpdate.js index e0176c2..8811d00 100644 --- a/node_modules/mongoose/lib/services/query/castUpdate.js +++ b/node_modules/mongoose/lib/services/query/castUpdate.js @@ -144,7 +144,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { // $currentDate can take an object obj[key] = castUpdateVal(schematype, val, op); hasKeys = true; - } else if (op === '$set' && schematype) { + } else if (op in castOps && schematype) { obj[key] = castUpdateVal(schematype, val, op); hasKeys = true; } else { @@ -171,7 +171,7 @@ function walkUpdatePath(schema, obj, op, strict, pref) { // we should be able to set a schema-less field // to an empty object literal hasKeys |= walkUpdatePath(schema, val, op, strict, prefix + key) || - (utils.isObject(val) && Object.keys(val).length === 0); + (utils.isObject(val) && Object.keys(val).length === 0); } } else { var checkPath = (key === '$each' || key === '$or' || key === '$and') ? @@ -233,7 +233,8 @@ var castOps = { $push: 1, $pushAll: 1, $addToSet: 1, - $set: 1 + $set: 1, + $setOnInsert: 1 }; /*! diff --git a/node_modules/mongoose/package.json b/node_modules/mongoose/package.json index b2a0761..c66f42c 100644 --- a/node_modules/mongoose/package.json +++ b/node_modules/mongoose/package.json @@ -2,25 +2,25 @@ "_args": [ [ { - "raw": "mongoose@4.9.3", + "raw": "mongoose@4.9.4", "scope": null, "escapedName": "mongoose", "name": "mongoose", - "rawSpec": "4.9.3", - "spec": "4.9.3", + "rawSpec": "4.9.4", + "spec": "4.9.4", "type": "version" }, - "/Users/Sasha/Desktop/Seng513-GroupProject" + "F:\\OneDrive\\Documents\\UofC Winter 2017\\SENG 513\\Seng513-GroupProject" ] ], - "_from": "mongoose@4.9.3", - "_id": "mongoose@4.9.3", + "_from": "mongoose@4.9.4", + "_id": "mongoose@4.9.4", "_inCache": true, "_location": "/mongoose", "_nodeVersion": "7.6.0", "_npmOperationalInternal": { - "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/mongoose-4.9.3.tgz_1491171706279_0.06217193859629333" + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/mongoose-4.9.4.tgz_1491765545070_0.7652687972877175" }, "_npmUser": { "name": "vkarpov15", @@ -29,23 +29,23 @@ "_npmVersion": "4.1.2", "_phantomChildren": {}, "_requested": { - "raw": "mongoose@4.9.3", + "raw": "mongoose@4.9.4", "scope": null, "escapedName": "mongoose", "name": "mongoose", - "rawSpec": "4.9.3", - "spec": "4.9.3", + "rawSpec": "4.9.4", + "spec": "4.9.4", "type": "version" }, "_requiredBy": [ "#USER", "/" ], - "_resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.9.3.tgz", - "_shasum": "7e3ea176ed7d3d23940368704834890595aea040", + "_resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.9.4.tgz", + "_shasum": "212be4597e2db57b05286cc53ee894f30f3d8fad", "_shrinkwrap": null, - "_spec": "mongoose@4.9.3", - "_where": "/Users/Sasha/Desktop/Seng513-GroupProject", + "_spec": "mongoose@4.9.4", + "_where": "F:\\OneDrive\\Documents\\UofC Winter 2017\\SENG 513\\Seng513-GroupProject", "author": { "name": "Guillermo Rauch", "email": "guillermo@learnboost.com" @@ -107,13 +107,13 @@ "lib": "./lib/mongoose" }, "dist": { - "shasum": "7e3ea176ed7d3d23940368704834890595aea040", - "tarball": "https://registry.npmjs.org/mongoose/-/mongoose-4.9.3.tgz" + "shasum": "212be4597e2db57b05286cc53ee894f30f3d8fad", + "tarball": "https://registry.npmjs.org/mongoose/-/mongoose-4.9.4.tgz" }, "engines": { "node": ">=0.6.19" }, - "gitHead": "86d6f732e985a49c1068a40ecba7df8ee576bc7e", + "gitHead": "d4d2d0156613f6dfbc269d7a590e2b5b997963d3", "homepage": "http://mongoosejs.com", "keywords": [ "mongodb", @@ -167,5 +167,5 @@ "test": "mocha test/*.test.js test/**/*.test.js", "test-cov": "istanbul cover --report text --report html _mocha test/*.test.js" }, - "version": "4.9.3" + "version": "4.9.4" } diff --git a/package.json b/package.json index b5b9d70..e845e75 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,9 @@ "version": "0.0.1", "description": "", "dependencies": { + "body-parser": "^1.17.1", "compute-covariance": "^1.0.1", + "csvtojson": "^1.1.4", "express": "^4.14.1", "express-fileupload": "^0.1.2", "firebase": "^3.7.4", diff --git a/public/css/project.css b/public/css/project.css index e427c35..5934e3f 100644 --- a/public/css/project.css +++ b/public/css/project.css @@ -737,4 +737,5 @@ input[type="radio"]:checked:before { dataset-card{ -} \ No newline at end of file +} + diff --git a/public/js/client.js b/public/js/client.js index 5da3f4c..cf4df66 100755 --- a/public/js/client.js +++ b/public/js/client.js @@ -219,11 +219,12 @@ $(function () { function style(feature) { return { - // fillColor: getColor(feature.properties.pop_est), + fillColor: "white", weight: 0, opacity: 1, - color: 'white', - fillOpacity: 0.0 + color: '#242426', + dashArray: '0', + fillOpacity: 0.66 }; } @@ -231,10 +232,11 @@ $(function () { var layer = e.target; layer.setStyle({ - weight: 1, - color: '#666', + weight: 0, + color: 'black', dashArray: '', - fillOpacity: 0.7 + fillOpacity: 0.66, + fillColor: "white" }); if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) { @@ -246,12 +248,15 @@ $(function () { function resetHighlight(e) { // geojson.resetStyle(e.target); e.target.setStyle({ - weight: 2, + fillColor: "white", + weight: 0, opacity: 1, - color: 'white', - dashArray: '3' + color: '#242426', + dashArray: '0', + fillOpacity: 0.66 }); + colorDataset("#f", "#00FF96"); info.update(); } @@ -272,7 +277,7 @@ $(function () { onEachFeature: onEachFeature }).addTo(map); - colorDataset("#FF2E00", "#00FF96"); + colorDataset("#f", "#00FF96"); var info = L.control(); @@ -320,7 +325,7 @@ $(function () { let numberOfItems = 10; let rainbow = new Rainbow(); rainbow.setNumberRange(1, numberOfItems); - rainbow.setSpectrum("#FF2E00", "#FFAE00", "#00FF96", "#FF0097"); + rainbow.setSpectrum("#808080", "#606060", "#404040", "#202020"); let colors = []; let cutPoints = []; @@ -379,11 +384,11 @@ $(function () { layer.setStyle({ fillColor: color, - weight: 2, + weight: 0, opacity: 1, - color: 'white', - dashArray: '3', - fillOpacity: 0.7 + color: '#242426', + dashArray: '0', + fillOpacity: 0.66 }); }); } diff --git a/public/js/project.js b/public/js/project.js index 96a52e4..90f98c9 100644 --- a/public/js/project.js +++ b/public/js/project.js @@ -5,6 +5,7 @@ $(function () { $('[data-toggle="popover"]').popover(); let userDatasets = null; + let curentUserID = null; var urlParams; (window.onpopstate = function () { @@ -43,6 +44,7 @@ $(function () { setupViewOnlyProject(urlParams.projectid, socket); } else if (firebaseUser) { console.log(firebaseUser); + curentUserID = firebaseUser.uid; //Redirect to the maps page $('#loading').fadeIn('slow'); @@ -54,19 +56,54 @@ $(function () { } }); - $('#uploadForm').submit(function () { - $("#status").empty().text("File is uploading..."); - $(this).ajaxSubmit({ - error: function (xhr) { - status('Error: ' + xhr.status); - }, - success: function (response) { - console.log(response) - $("#status").empty().text(response); - } + // Display modal to add new dataset + $('#createNewDatasetCard').on('click', () => { + $('#newDatasetModal').modal('show'); + }); + + //after the template download display next step on dataset upload + $('#datasetNextStepButton').on('click', () => { + $('#newDatasetModalLabel').text("Upload your filled in template data"); + $('#newDatasetModalBody').html('' + + '
'); + $("#datasetNextStepButton").hide(); + $("#createNewDatasetButton").removeClass('hidden').show(); + + $('#createNewDatasetButton').on("click", function () { + console.log("Sending file..."); + + var formdata = new FormData($('#uploadForm')[0]); + formdata.append('userid', curentUserID); + formdata.append('datasetname', $('#newDatasetName').val()); + + console.log(formdata); + + $.ajax({ + url: "/api/dataset", + type: "POST", + data: formdata, + processData: false, + contentType: false, + success: function (res) { + console.log(res); + $('#newDatasetModal').modal('hide'); + } + }); }); }); + $('#newDatasetModal').on('hidden.bs.modal', function (e) { + console.log("Hidding upload ds"); + + $('#newDatasetModalBody').html('