159 lines
4.6 KiB
JavaScript
159 lines
4.6 KiB
JavaScript
|
const _ = require('underscore');
|
||
|
const Backbone = require('backbone');
|
||
|
const SQL = require('internal-carto.js').SQL;
|
||
|
const WKT = require('dashboard/common/wkt');
|
||
|
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||
|
|
||
|
const REQUIRED_OPTS = [
|
||
|
'configModel'
|
||
|
];
|
||
|
|
||
|
const RESERVED_COLUMNS = 'the_geom the_geom_webmercator cartodb_id created_at updated_at'.split(' ');
|
||
|
|
||
|
module.exports = Backbone.Model.extend({
|
||
|
|
||
|
_GEOMETRY_TYPES: {
|
||
|
'point': 'st_point',
|
||
|
'multipoint': 'st_multipoint',
|
||
|
'linestring': 'st_linestring',
|
||
|
'multilinestring': 'st_multilinestring',
|
||
|
'polygon': 'st_polygon',
|
||
|
'multipolygon': 'st_multipolygon'
|
||
|
},
|
||
|
|
||
|
initialize: function (attrs, opts) {
|
||
|
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||
|
},
|
||
|
|
||
|
url: function (method) {
|
||
|
var version = this._configModel.urlVersion('record', method);
|
||
|
var table = this.table || this.collection.table;
|
||
|
if (!table) {
|
||
|
console.error('row has no table assigned');
|
||
|
}
|
||
|
|
||
|
var base = '/api/' + version + '/tables/' + table.get('name') + '/records/';
|
||
|
if (this.isNew()) {
|
||
|
return base;
|
||
|
}
|
||
|
return base + this.id;
|
||
|
},
|
||
|
|
||
|
fetch: function (opts) {
|
||
|
opts = opts || {};
|
||
|
var username = (this.options && this.options.user_data) ? this.options.user_data.username
|
||
|
: (window.user_data ? window.user_data.username : window.user_name);
|
||
|
var api_key = (this.options && this.options.user_data) ? this.options.user_data.api_key
|
||
|
: (window.user_data ? window.user_data.api_key : window.api_key);
|
||
|
|
||
|
var table = this.table || this.collection.table;
|
||
|
|
||
|
var sqlApi = new SQL({
|
||
|
user: username,
|
||
|
version: 'v2',
|
||
|
api_key: api_key,
|
||
|
sql_api_template: this._configModel.getSqlApiBaseUrl(),
|
||
|
extra_params: ['skipfields']
|
||
|
});
|
||
|
// this.trigger('loading')
|
||
|
var sql = null;
|
||
|
var columns = table.columnNames();
|
||
|
if (opts.no_geom) {
|
||
|
columns = _.without(columns, 'the_geom', 'the_geom_webmercator');
|
||
|
} else {
|
||
|
columns = _.without(columns, 'the_geom');
|
||
|
}
|
||
|
sql = 'SELECT ' + columns.join(',') + ' ';
|
||
|
if (table.containsColumn('the_geom') && !opts.no_geom) {
|
||
|
sql += ',ST_AsGeoJSON(the_geom, 8) as the_geom ';
|
||
|
}
|
||
|
sql += ' from (' + table.data().getSQL() + ') _table_sql WHERE cartodb_id = ' + this.get('cartodb_id');
|
||
|
// Added opts to sql execute function to apply
|
||
|
// parameters ( like cache ) to the ajax request
|
||
|
if (opts.no_geom) {
|
||
|
opts.skipfields = 'the_geom,the_geom_webmercator';
|
||
|
} else {
|
||
|
opts.skipfields = 'the_geom_webmercator';
|
||
|
}
|
||
|
sqlApi.execute(sql, {}, opts).done(function (data) {
|
||
|
if (this.parse(data.rows[0])) {
|
||
|
this.set(data.rows[0]);//, {silent: silent});
|
||
|
this.trigger('sync');
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
toJSON: function () {
|
||
|
var attr = _.clone(this.attributes);
|
||
|
// remove read-only attributes
|
||
|
delete attr['updated_at'];
|
||
|
delete attr['created_at'];
|
||
|
delete attr['the_geom_webmercator'];
|
||
|
if (!this.isGeometryGeoJSON()) {
|
||
|
delete attr['the_geom'];
|
||
|
}
|
||
|
return attr;
|
||
|
},
|
||
|
|
||
|
isGeomLoaded: function () {
|
||
|
var geojson = this.get('the_geom');
|
||
|
var column_types_WKT = WKT.types;
|
||
|
return (geojson !== 'GeoJSON' && geojson !== -1 && !_.contains(column_types_WKT, geojson));
|
||
|
},
|
||
|
|
||
|
hasGeometry: function () {
|
||
|
var the_geom = this.get('the_geom');
|
||
|
return !!(the_geom != null && the_geom != undefined && the_geom != ''); // eslint-disable-line eqeqeq
|
||
|
},
|
||
|
/**
|
||
|
* Checks if the_geom contains a valid geoJson
|
||
|
*/
|
||
|
isGeometryGeoJSON: function () {
|
||
|
var the_geom = this.get('the_geom');
|
||
|
if (the_geom && typeof the_geom === 'object') {
|
||
|
return !!the_geom.coordinates;
|
||
|
} else if (typeof the_geom !== 'string') {
|
||
|
return false;
|
||
|
}
|
||
|
// if the geom contains GeoJSON, the row has a valid geometry, but is not loaded yet
|
||
|
if (the_geom === 'GeoJSON') {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
var g = JSON.parse(the_geom);
|
||
|
return !!g.coordinates;
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getFeatureType: function () {
|
||
|
if (this.isGeomLoaded()) {
|
||
|
// Problem geometry type from a WKB format
|
||
|
// Not possible for the moment
|
||
|
try {
|
||
|
var geojson = JSON.parse(this.get('the_geom'));
|
||
|
return geojson.type.toLowerCase();
|
||
|
} catch (e) {
|
||
|
console.info('Not possible to parse geometry type');
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
},
|
||
|
|
||
|
getGeomType: function () {
|
||
|
try {
|
||
|
return this._GEOMETRY_TYPES[this.getFeatureType()];
|
||
|
} catch (e) {
|
||
|
console.info('Not possible to parse geometry type');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}, {
|
||
|
RESERVED_COLUMNS,
|
||
|
isReservedColumn: function (c) {
|
||
|
return _(RESERVED_COLUMNS).indexOf(c) !== -1;
|
||
|
}
|
||
|
});
|