Skip to content
Browse files

Implemented rudimentary shp support

  • Loading branch information...
1 parent d4f03ca commit 2555a3d3f771c385279403fd065895d993c87ce0 @samluescher samluescher committed Feb 8, 2013
View
89 api/import/conversion/index.js
@@ -1,4 +1,5 @@
var utils = require('../../../utils.js'),
+ ValidationError = utils.ValidationError,
console = require('../../../ext-console.js'),
_ = require('cloneextend');
@@ -197,6 +198,22 @@ var FieldType = {
return [arr[1], arr[0]];
}
}
+ },
+
+ Object: function(fromFields, options) {
+ var fromFields = Cast.Array(fromFields);
+ var l = fromFields.length;
+ var options = options || {};
+ return function() {
+ var val = {};
+ for (var i = 0; i < l; i++) {
+ var obj = this.get(fromFields[i]);
+ if (typeof obj == 'object') {
+ val = _.cloneextend(val, obj);
+ }
+ }
+ return val;
+ }
}
}
@@ -221,8 +238,19 @@ fieldDefs = {
}
*/
-var Converter = function(fields) {
+var Converter = function(fieldDefs) {
+ var fields = {};
+ if (typeof fieldDefs != 'object') {
+ fieldDefs = {};
+ }
+
+ for (var toField in fieldDefs) {
+ var d = fieldDefs[toField];
+ fields[toField] = FieldType[d.type](d.fromFields || toField, d.options);
+ }
+
this.fields = fields;
+ this.fieldDefs = fieldDefs;
};
Converter.prototype.convertModel = function(fromModel, toModel) {
@@ -236,18 +264,67 @@ Converter.prototype.convertModel = function(fromModel, toModel) {
}
}
var m = new toModel(doc);
+ console.log('...............', m, doc);
return m;
};
module.exports = {
Converter: Converter,
ConversionError: ConversionError,
- ConverterFactory: function(fieldDefs) {
- var fields = {}
+ PointConverterFactory: function(fieldDefs) {
+ var errors = {},
+ valid = true;
+ if (typeof fieldDefs != 'object') {
+ fieldDefs = {};
+ }
+
for (var toField in fieldDefs) {
- var d = fieldDefs[toField];
- fields[toField] = FieldType[d.type](d.fromFields, d.options);
+ var d = fieldDefs[toField],
+ t;
+ switch (toField) {
+ default:
+ if (!d.type || !FieldType[d.type]) {
+ d.type = 'String';
+ }
+ break;
+ case 'loc':
+ if (d.type != 'LatLng') {
+ d.type = 'LngLat';
+ }
+ break;
+ case 'val':
+ d.type = 'Number';
+ break;
+ case 'datetime':
+ d.type = 'Date';
+ break;
+ case 'label':
+ d.type = 'String';
+ break;
+ }
+
+ if (d.fromFields && (typeof d.fromFields == 'string' || (Array.isArray(d.fromFields) && d.fromFields.length > 0))) {
+ console.log('validated converter field definition', toField, d);
+ } else {
+ console.error('invalid converter field definition', toField, d);
+ valid = false;
+ errors[toField] = {
+ message: 'field ' + toField + ' has no Element fromFields'
+ };
+ }
+ }
+
+ if (!fieldDefs.loc) {
+ valid = false;
+ errors[toField] = {
+ message: 'Point X,Y is required'
+ };
+ }
+
+ if (valid) {
+ return new Converter(fieldDefs);
+ } else {
+ return new ValidationError(errors);
}
- return new Converter(fields);
}
}
View
138 api/import/conversion/point/base.js
@@ -1,138 +0,0 @@
-var ConversionError = this.ConversionError = require('../').ConversionError;
-
-var clamp180 = this.clamp180 = function(deg)
-{
- if (deg < -360 || deg > 360) {
- deg = deg % 360;
- }
- if (deg < -180) {
- deg = 180 + deg % 180;
- }
- if (deg > 180) {
- deg = 180 - deg % 180;
- }
- if (deg == 180) {
- deg = -180;
- }
-
- return deg;
-};
-
-/**
-* Converts a string like ' y.yyy , -xx.x' to [x, y]
-*/
-this.latLngWithCommaFromString = function(field, latIndex, lngIndex)
-{
- var latI = latIndex != undefined ? latIndex : 0;
- var lngI = latIndex != undefined ? latIndex : 1;
- return function() {
- var match = String(this.get(field)).match(/^\s*([0-9\.\-]+)\s*[,\ ]\s*([0-9\.\-]+)\s*$/);
- if (match) {
- return [clamp180(parseFloat(match[lngI + 1])), clamp180(parseFloat(match[latI + 1]))]
- };
- return new ConversionError('string not matching supported format: '+this.get(field));
- }
-};
-
-/**
-* Converts a string like ' y.yyy , -xx.x' to [x, y]
-*/
-this.smartLatLng = function(field)
-{
- var fromStringFuncs = [
- this.latLngWithCommaFromString('loc'),
- this.latLngWithCommaFromString('location')
- ];
- return function() {
- var lng = this.get('longitude') || this.get('lng') || this.get('lon') || this.get('x'),
- lat = this.get('latitude') || this.get('lat') || this.get('y');
- if (!lng || !lat) {
- var val = this.get('loc') || this.get('location');
- if (val instanceof Array) {
- lng = val[0];
- lat = val[1];
- }
- }
- if (lng && lat) {
- lng = parseFloat(lng);
- lat = parseFloat(lat);
- if (!isNaN(lng) && !isNaN(lat)) {
- var a = [clamp180(lng), clamp180(lat)];
- return a;
- }
- }
- for (var i = 0; i < fromStringFuncs.length; i++) {
- var conv = fromStringFuncs[i].apply(this);
- if (!(conv instanceof ConversionError)) {
- break;
- }
- }
- return conv;
- }
-};
-
-
-/**
-* Converts a string like ' y.yyy , -xx.x' to [x, y]
-*/
-this.locFromFields = function(lngFields, latFields)
-{
- if (typeof lngFields == 'string') {
- var lngFields = [lngFields];
- }
- if (typeof latFields == 'string') {
- var latFields = [latFields];
- }
-
- return function() {
- var lng, lat;
- for (var i = 0; i < lngFields.length; i++) {
- var lng = this.get(lngFields[i]);
- if (lng != undefined) break;
- }
- for (var i = 0; i < latFields.length; i++) {
- var lat = this.get(latFields[i]);
- if (lat != undefined) break;
- }
- lngF = parseFloat(lng);
- latF = parseFloat(lat);
- if (!isNaN(lngF) && !isNaN(latF) && lng != undefined && lat != undefined) {
- return [clamp180(lngF), clamp180(latF)]
- };
- return new ConversionError('invalid lng,lat: '+lng+','+lat);
- }
-};
-
-// TODO: Repair base converter
-this.fields = {
- val: function() {
- var val = this.get('val');
- if (val) {
- return parseFloat(val);
- }
- return null;
- }
- ,datetime: function() {
- var d = Date.parse(String(this.get('date')));
- if (d) {
- return new Date(d);
- }
- return null;
- }
- ,label: function() {
- return this.get('label') || this.get('name');
- }
- ,loc: this.smartLatLng()
- ,sourceId: function() {
- var id = this.get('sourceId');
- if (id) {
- numId = parseInt(id);
- if (!isNaN(numId)) {
- return numId;
- }
- return id;
- }
- return null;
- }
-};
-
View
173 api/import/index.js
@@ -2,6 +2,7 @@ var config = require('../../config.js'),
models = require("../../models.js"),
permissions = require("../../permissions.js"),
utils = require("../../utils.js"),
+ ValidationError = utils.ValidationError,
conversion = require("./conversion"),
mongoose = require('mongoose'),
date = require('datejs'),
@@ -11,24 +12,52 @@ var config = require('../../config.js'),
console = require('../../ext-console.js'),
MapReduceAPI = require('../mapreduce');
-var Point = models.Point,
- PointCollection = models.PointCollection,
- LayerOptions = models.LayerOptions,
+var LayerOptions = models.LayerOptions,
handleDbOp = utils.handleDbOp;
var ImportAPI = function(app) {
var self = this;
if (app) {
app.post('/api/import/', function(req, res) {
- // prevent arbitrary script inclusion:
+ if (!permissions.canImportData(req)) {
+ res.send('', 403);
+ return;
+ }
+ // prevent arbitrary script inclusion
if (req.body.converter) {
req.body.converter = path.basename('' + req.body.converter);
}
if (req.body.format) {
req.body.format = path.basename('' + req.body.format);
}
+ // prevent arbitrary file import
+ req.body.path = null;
+
+ var errors = {};
+ var valid = true;
+ if (!req.body.url) {
+ valid = false;
+ errors.url = {
+ message: 'URL is missing'
+ };
+ }
+
+ var converter = conversion.PointConverterFactory(req.body.fields);
+ if (converter instanceof ValidationError) {
+ valid = false;
+ errors = _.cloneextend(errors, converter.errors);
+ } else {
+ req.body.converter = converter;
+ }
+
+ req.body.mapreduce = true;
- self.import(req.body, req, res);
+ if (!valid) {
+ var err = new ValidationError(errors);
+ res.send(err, 403);
+ } else {
+ self.import(req.body, req, res);
+ }
});
}
}
@@ -56,7 +85,6 @@ ImportAPI.prototype.import = function(params, req, res, callback)
var defaults = {
url: null, path: null, stream: null,
format: null,
- converter: 'base',
max: 0,
interval: 1,
skip: 0,
@@ -108,14 +136,6 @@ ImportAPI.prototype.import = function(params, req, res, callback)
}
throw err;
}
- if (typeof params.converter != 'string') {
- var err = new Error('invalid converter: ' + params.converter);
- if (callback) {
- callback(err);
- return;
- }
- throw err;
- }
if (params.bounds) {
if (typeof params.bounds == 'string') {
@@ -134,17 +154,30 @@ ImportAPI.prototype.import = function(params, req, res, callback)
}
console.log('import params', params);
- var Converter, format, parser;
+ var Converter, converter, format, parser;
- if (!params.converter) {
- params.converter = 'base';
- }
- if (params.converter.match(REGEX_IS_REGULAR_MODULE)) {
- Converter = require('./conversion/point/'
- + params.converter);
+ if (params.fields) {
+ console.log('Initializing converter with fieldDefs');
+ Converter = function() { return conversion.PointConverterFactory(params.fields) };
} else {
- console.log('Loading custom converter: '+params.converter);
- Converter = require(params.converter);
+ if ((typeof params.converter != 'string' && typeof params.converter != 'object')
+ || (typeof params.converter == 'object' && !params.converter.fields)) {
+ var err = new Error('invalid converter: ' + params.converter);
+ if (callback) {
+ callback(err);
+ return;
+ }
+ throw err;
+ } else if (typeof params.converter == 'string') {
+ if (params.converter.match(REGEX_IS_REGULAR_MODULE)) {
+ Converter = require('./conversion/' + params.converter);
+ } else {
+ console.log('Loading custom converter: '+params.converter);
+ Converter = require(params.converter);
+ }
+ } else {
+ converter = params.converter;
+ }
}
if (params.format.match(REGEX_IS_REGULAR_MODULE)) {
@@ -172,7 +205,9 @@ ImportAPI.prototype.import = function(params, req, res, callback)
var runImport = function(collection)
{
- var converter = new Converter(params.fields);
+ if (!converter) {
+ converter = new Converter(params.fields);
+ }
if (!converter.convertModel) {
var err = new Error('converter module does not export `convertModel`');
if (callback) {
@@ -183,14 +218,13 @@ ImportAPI.prototype.import = function(params, req, res, callback)
}
var headerValues = {};
+
collection.active = false;
collection.status = config.DataStatus.IMPORTING;
if (params.saveParams == undefined || params.saveParams) {
- collection.importParams = params;
- // TODO re-init converter with fields
- /*if (params.fields || params.converter) {
- collection.importParams.fields = converter.fields;
- }*/
+ collection.importParams = _.cloneextend(params, {
+ fields: converter.fieldDefs
+ });
}
if (req && req.session) {
collection.createdBy = collection.modifiedBy = req.session.user;
@@ -208,7 +242,8 @@ ImportAPI.prototype.import = function(params, req, res, callback)
}
var newCollectionId = collection.get('_id');
- console.success('* saved PointCollection "'+collection.get('title')+'" = '+newCollectionId);
+ console.success('* saved '+collection.name+' "'+collection.get('title')+'" = '+newCollectionId);
+ console.log(collection);
var job = new models.Job({status: config.JobStatus.ACTIVE, type: config.JobType.IMPORT});
job.save(function(err, job) {
@@ -393,7 +428,7 @@ ImportAPI.prototype.import = function(params, req, res, callback)
}
var model = new Model(doc);
- var point = converter.convertModel(model, Point);
+ var point = converter.convertModel(model, ToModel);
point.importJob = job;
var loc = point ? point.get('loc') : null;
var doSave = point
@@ -407,7 +442,7 @@ ImportAPI.prototype.import = function(params, req, res, callback)
self.readStream.pause();
paused = true;
}
- point.pointCollection = collection;
+ point.pointCollection = point.shapeCollection = collection;
point.created = new Date();
point.modified = new Date();
if (maxVal == undefined || maxVal < point.get('val')) {
@@ -502,46 +537,44 @@ ImportAPI.prototype.import = function(params, req, res, callback)
});
};
- var converterInit = Converter.init || function(callback) {
- callback();
- };
- converterInit(function() {
- if (!params.append) {
- console.info('*** Creating new collection ***');
- var defaults = new LayerOptions(config.COLLECTION_DEFAULTS);
- for (var key in config.COLLECTION_DEFAULTS) {
- if (params[key]) {
- defaults[key] = params[key];
- }
+ var ToModel = models.Shape,
+ ToCollectionModel = models.ShapeCollection;
+
+ if (!params.append) {
+ console.info('*** Creating new collection ***');
+ var defaults = new LayerOptions(config.COLLECTION_DEFAULTS);
+ for (var key in config.COLLECTION_DEFAULTS) {
+ if (params[key]) {
+ defaults[key] = params[key];
}
- defaults.save(function(err, res) {
- if (err) {
- console.error(err.message);
- if (res) {
- res.send('server error', 500);
- if (callback) {
- callback(err);
- }
+ }
+ defaults.save(function(err, res) {
+ if (err) {
+ console.error(err.message);
+ if (res) {
+ res.send('server error', 500);
+ if (callback) {
+ callback(err);
}
- return;
}
- runImport(new PointCollection({
- defaults: defaults._id,
- title: params.title || path.basename(params.url || params.path),
- description: params.description,
- unit: "",
- progress: 0,
- }));
- });
+ return;
+ }
+ runImport(new ToCollectionModel({
+ defaults: defaults._id,
+ title: params.title || path.basename(params.url || params.path),
+ description: params.description,
+ unit: "",
+ progress: 0,
+ }));
+ });
- } else {
- console.info('*** Appending to collection ***', params.append);
- PointCollection.findOne({_id: params.append}, function(err, collection) {
- if (!utils.validateExistingCollection(err, collection, callback)) return;
- runImport(collection);
- });
- }
- });
+ } else {
+ console.info('*** Appending to collection ***', params.append);
+ ToCollectionModel.findOne({_id: params.append}, function(err, collection) {
+ if (!utils.validateExistingCollection(err, collection, callback)) return;
+ runImport(collection);
+ });
+ }
}
ImportAPI.prototype.sync = function(params, req, res, callback)
@@ -601,7 +634,7 @@ function getImportParams(params)
url: params.u || params.url,
path: params.p || params.path,
format: params.f || params.format,
- converter: params.c || params.converter,
+ converter: params.c || params.converter,
append: params.append,
from: params.from,
to: params.to,
@@ -612,7 +645,7 @@ function getImportParams(params)
interval: params.interval,
bounds: params.bounds,
mapreduce: params.mapreduce,
- fields: (params.fields ? JSON.parse(params.fields) : undefined)
+ fields: (params.fields ? JSON.parse(params.fields) : undefined) // precedence over converter
});
}
View
11 models.js
@@ -56,17 +56,14 @@ this.Point.schema.plugin(useTimestamps);
this.Point.schema.index({loc: '2d', pointCollection: 1})
this.Shape = mongoose.model('Shape', new mongoose.Schema({
- pointCollection: { type: mongoose.Schema.ObjectId, ref: 'PointCollection', required: true, index: 1 },
- loc: {type: [Number], index: '2d', required: true},
+ shapeCollection: { type: mongoose.Schema.ObjectId, ref: 'ShapeCollection', required: true, index: 1 },
type: {type: String, required: true},
- geometry: {type: String, required: true},
- label: String,
- url: String,
- datetime: {type: Date, index: 1},
+ geometry: mongoose.Schema.Types.Mixed,
+ properties: mongoose.Schema.Types.Mixed
}));
this.Shape.schema.plugin(useTimestamps);
-this.Shape.schema.index({loc: '2d', pointCollection: 1})
+this.Shape.schema.index({ws: '2d', en: '2d', shapeCollection: 1})
this.ColorDefinition = mongoose.model('ColorDefinition', new mongoose.Schema({
color: {type: String, required: true},
View
4 permissions.js
@@ -26,3 +26,7 @@ exports.canViewMap = function(req, map) {
exports.canCreateMap = function(req) {
return !config.LIMITED_PROD_ACCESS;
}
+
+exports.canImportData = function(req) {
+ return !config.LIMITED_PROD_ACCESS;
+}
View
59 public/styles/add-data.css
@@ -30,11 +30,44 @@
width:100px;
}
-.add-data-view .modal-body .data-table
+.add-data-view .modal-body table
{
- max-height:200px;
- height:200px;
- overflow:scroll;
+ max-height: 100px;
+ height: 100px;
+ overflow: scroll;
+ width: 100%;
+}
+
+.add-data-view .modal-body table th, .add-data-view .modal-body table td {
+ padding: .2em;
+}
+
+.add-data-view th ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+.from-field .remove {
+ display: none;
+}
+
+.to-field .from-field .remove {
+ display: inline-block;
+}
+
+.add-data-view .to-field {
+ min-height: 30px;
+ border: 1px #eee dashed;
+ background: white;
+}
+
+.add-data-view .to-field .from-field {
+ display: inline-block;
+}
+
+.drop-field.sortable .drag-field:last-child {
+ margin-right: .25em;
}
.add-data-view .modal-body .alert
@@ -60,24 +93,6 @@
cursor:pointer;
}
-.label.to-field-lat {
- background-color: #c43c35;
- padding:10px;
-
-}
-.label.to-field-lng {
- background-color: #f89406;
- padding:10px;
-}
-.label.to-field-val {
- background-color: #46a546;
- padding:10px;
-}
-.label.to-field-label {
- background-color: #62cffc;
- padding:10px;
-}
-
.add-data-view .modal.large
{
View
4 public/styles/global.css
@@ -63,6 +63,10 @@ html {
}
+.element-template {
+ display: none;
+}
+
body {
background-color:#edeeee;
font-family: Helvetica, Helvetica Neue, Arial, sans-serif;
View
82 public/templates/add-data.html
@@ -6,6 +6,7 @@ <h3 class="title">Add Your Awesome Data</h3>
<div class="modal-body">
<!-- Selecting Data Source/File -->
+ <!--
<div class="add">
<div class="well form-inline">
@@ -40,19 +41,77 @@ <h3 class="title">Add Your Awesome Data</h3>
</div>
</div>
</div>
+-->
<!-- Review data -->
<div class="review">
- <label>Almost there! Drag the labels below onto their matching columns</label>
- <div class="well">
- <div>
- <span class="drag label to-field-lat">Latitude</span>
- <span class="drag label to-field-lng">Longitude</span>
- <span class="drag label to-field-label">Point Label</span>
- <span class="drag label to-field-val">Point Value</span>
- </div>
- </div>
- <div class="data-table" id="dataTable"></div>
+ <div class="well">
+ <table class="from-data table-striped">
+ <thead>
+ <tr>
+ <th class="element-template">
+ <ul>
+ <li class="from-field" data-from="">
+ <span class="label"><span class="name"></span> <a href="" class="remove"><span class="icon icon-white icon-remove"></a></span></span>
+ </li>
+ </ul>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+ </div>
+ <div class="well">
+ <table class="to-data table-striped">
+ <thead>
+ <tr>
+ <th class="element-template">
+ <span class="label name to-field-name"></span>
+ <ul class="to-field" data-to=""></ul>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>16.123123,12.213123</td>
+ <td>Foo</td>
+ <td>3.9</td>
+ <td>dasdasdas</td>
+ </tr>
+ <tr>
+ <td>asd16.123123,12.213123</td>
+ <td>Foo</td>
+ <td>3.9</td>
+ <td>dasdasdas</td>
+ </tr>
+ <tr>
+ <td>asd16.123123,12.213123</td>
+ <td>Foo</td>
+ <td>3.9</td>
+ <td>dasdasdas</td>
+ </tr>
+ <tr>
+ <td>asd16.123123,12.213123</td>
+ <td>Foo</td>
+ <td>3.9</td>
+ <td>dasdasdas</td>
+ </tr>
+ <tr>
+ <td>asd16.123123,12.213123</td>
+ <td>Foo</td>
+ <td>3.9</td>
+ <td>dasdasdas</td>
+ </tr>
+ <tr>
+ <td>asd16.123123,12.213123</td>
+ <td>Foo</td>
+ <td>3.9</td>
+ <td>dasdasdas</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
</div>
<!-- Alerts -->
@@ -62,8 +121,7 @@ <h3 class="title">Add Your Awesome Data</h3>
</div>
</div>
<div class="modal-footer">
- <a href="#" id="dataConfirmButton" class="btn btn-success">Confirm and Add</a>
- <a href="#" id="dataButton" class="btn btn-primary">Next: Review Data</a>
+ <a href="#" id="importButton" class="btn btn-primary">Import Data</a>
<a href="#" data-dismiss="modal" class="btn">Close</a>
</div>
</div>
View
173 public/views/add-data-view.js
@@ -12,8 +12,8 @@ define([
className: 'add-data-view',
events: {
- 'click #dataButton': 'dataButtonClicked',
- 'click #dataConfirmButton' : 'dataConfirmButtonClicked',
+ 'click #importButton': 'importButtonClicked',
+ 'click .from-field .remove' : 'fromFieldRemoveClicked',
},
initialize: function(options) {
@@ -27,91 +27,132 @@ define([
render: function() {
$(this.el).html(this.template());
var self = this;
+ this.$('.modal').addClass('large');
+
+ this.fromFieldTemplate = this.$('.from-data thead .element-template');
+ this.toFieldTemplate = this.$('.to-data thead .element-template');
+ this.$('.element-template').remove();
- this.$('.drag.label').draggable({
- revert: true,
+ this.fromFieldColors = ['#c43c35', '#f89406', '#46a546', '#62cffc'];
+ this.fromFields = {
+ 'location': 'location',
+ 'Facility': 'Facility',
+ 'val': 'val',
+ 'year': 'year'
+ };
+
+ this.toFields = {
+ 'loc': 'Point X,Y',
+ 'val': 'Point Value',
+ 'datetime':'Date',
+ 'label': 'Point Label'
+ };
+
+ var i = 0;
+ for (var k in this.fromFields) {
+ var f = this.fromFieldTemplate.clone();
+ f.removeClass('element-template');
+ $('.name', f).text(this.fromFields[k]);
+ $('.label', f).css('background-color', this.fromFieldColors[i % this.fromFieldColors.length]);
+ $('.from-field', f).attr('data-from', k);
+ this.$('.from-data thead').append(f).show();
+ i++;
+ }
+
+ for (var k in this.toFields) {
+ var f = this.toFieldTemplate.clone();
+ f.removeClass('element-template');
+ $('.name', f).text(this.toFields[k]);
+ $('.to-field', f).attr('data-to', k);
+ this.$('.to-data thead').append(f).show();
+ }
+
+ this.$('.to-field').sortable({
+ connectWith: '.to-field'
+ });
+
+ this.$('.from-field').draggable({
+ revert: "invalid",
+ helper: "clone",
+ connectToSortable: '.to-field',
stack: '.drag.label'
});
- this.$('#map_canvas').droppable( {
- accept: '#dragLabel',
+ /*this.$('.drop-field').droppable( {
+ accept: '.drag-field',
hoverClass: '',
drop: self.handleCardDrop
- } );
+ } );*/
return this;
},
- handleCardDrop:function ( event, ui ) {
- var draggable = ui.draggable;
- alert( 'The square with ID "' + draggable.attr('id') + '" was dropped onto me!' );
- },
-
- dataButtonClicked: function() {
- //Todo: Verify string URL
- var self = this;
- this.dataTitle = this.$('#titleInput').val();
- this.dataDescription = this.$('#descriptionInput').val();
-
- // TODO: Add better validation
- if (true /* this.dataTitle != '' && this.$('#fileInput').val() != ''*/)
- {
- this.requestData();
+ fromFieldRemoveClicked: function(event) {
+ $(event.currentTarget).closest('.from-field').remove();
+ return false;
+ },
+
+ showAlert: function(html) {
+ if (!html) {
this.$('.modal-body .alert').hide();
- }
- else
- {
+ } else {
this.$('.modal-body .alert').show();
+ this.$('.modal-body .alert').html(html);
+ }
+ },
+
+ getFieldDefs: function() {
+ var defs = {};
+ for (var k in this.toFields) {
+ console.log(this.$('.to-field[data-to=' + k +'] .from-field'));
+ var fromFields = this.$('.to-field[data-to=' + k +'] .from-field');
+ defs[k] = {
+ fromFields: []
+ };
+ for (var i = 0; i < fromFields.length; i++) {
+ defs[k].fromFields.push($(fromFields[i]).attr('data-from'));
+ }
}
- },
+ return defs;
+ },
- dataConfirmButtonClicked: function()
- {
- //Todo: Validate fields
- //app.addData({data:this.responseData, title:this.dataTitle, description:this.dataDescription});
+ importButtonClicked: function() {
+ this.startImport();
},
- requestData:function(options)
+ startImport: function()
{
var self = this;
- dataType = 'csv';
- /*if(dataType == 'json')
- {
- var self = this;
- var jqxhr = $.getJSON(options.url, function(data) {})
- .success(function(data) {
- self.responseData = data;
- self.showDataReview(data);
- })
- .error(function(err) { alert(err); })
- .complete(function() {});
- }
- else*/ if (dataType == 'csv') {
- $.ajax({
- type: 'POST',
- url: '/api/import/',
- data: {
- file: this.$('#fileInput').val(),
- title: this.$('#titleInput').val(),
- description: this.$('#descriptionInput').val(),
- converter: this.$('#converter').val()
- },
- success: function(responseData) {
- if (responseData.pointCollectionId) {
- app.bindCollectionToMap(responseData.pointCollectionId);
- $('#addDataModal').modal('hide');
- } else {
- // TODO: error
+ self.$('#importButton').attr('disabled', true);
+ $.ajax({
+ type: 'POST',
+ url: '/api/import/',
+ data: {
+ url: 'https://dl.dropbox.com/s/03cqpv1camzz4a1/reactors.csv',
+ fields: this.getFieldDefs()
+ },
+ success: function(responseData) {
+ app.bindCollectionToMap(responseData.pointCollectionId);
+ $('#addDataModal').modal('hide');
+ self.close();
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ var data = $.parseJSON(jqXHR.responseText);
+ console.error('import failed', data.errors);
+ var lis = '';
+ if (data && data.errors) {
+ for (var k in data.errors) {
+ lis += '<li>' + data.errors[k].message + '</li>';
}
- },
- error: function() {
- console.error('failed to fetch unique map');
+ console.error('errors:', data.errors);
+ self.showAlert('<ul>' + lis + '</ul>');
}
- });
- }
+ self.$('#importButton').attr('disabled', false);
+ }
+ });
},
- showDataReview: function(data)
+/* showDataReview: function(data)
{
var self = this;
@@ -140,7 +181,7 @@ define([
});
});
- },
+ },*/
});
View
6 utils.js
@@ -25,6 +25,11 @@ exports.connectDB = function(callback, exitProcessOnError)
return mongoose.connect(config.DB_PATH).connection;
};
+exports.ValidationError = function(errors) {
+ Error.call(this);
+ this.errors = errors;
+}
+
/**
* Simple Python-style string formatting.
*
@@ -142,6 +147,7 @@ exports.handleDbOp = function(req, res, err, op, name, permissionCallback)
res.send(sendErr, 500);
break;
case 'ValidationError':
+ console.log(err);
// certain error messages should be available to client:
res.send(err, 403);
break;

0 comments on commit 2555a3d

Please sign in to comment.
Something went wrong with that request. Please try again.