cartodb/lib/assets/javascripts/builder/data/feature-definition-model.js

233 lines
6.0 KiB
JavaScript
Raw Normal View History

2020-06-15 10:58:47 +08:00
var _ = require('underscore');
var Backbone = require('backbone');
var QueryRowModel = require('./query-row-model');
var TYPES_POINT = 'point';
var TYPES_LINE = 'line';
var TYPES_POLYGON = 'polygon';
var GEOJSON_TO_FEATURE_TYPE = {
Point: TYPES_POINT,
MultiPoint: TYPES_POINT,
LineString: TYPES_LINE,
MultiLineString: TYPES_LINE,
Polygon: TYPES_POLYGON,
MultiPolygon: TYPES_POLYGON
};
var convertGeoJSONTypeToFeatureType = function (the_geom) {
var geoJSON = null;
try {
geoJSON = JSON.parse(the_geom);
} catch (err) {
// if the geom is not a valid json value
}
var geometryType = geoJSON && geoJSON.type;
var featureType = GEOJSON_TO_FEATURE_TYPE[geometryType];
if (!featureType) {
throw new Error("unsupported geometry type: '" + geometryType + "'");
}
return featureType;
};
var BLACKLISTED_COLUMNS = ['cartodb_id', 'created_at', 'the_geom_webmercator', 'updated_at'];
var FeatureDefinitionModel = Backbone.Model.extend({
initialize: function (attrs, options) {
if (!options.configModel) throw new Error('configModel is required');
if (!options.layerDefinitionModel) throw new Error('layerDefinitionModel is required');
if (!options.userModel) throw new Error('userModel is required');
this._configModel = options.configModel;
this._layerDefinitionModel = options.layerDefinitionModel;
this._userModel = options.userModel;
this._featureType = options.featureType;
this._firstNode = this._getAnalysisDefinitionNodeModel();
this._changesHistory = [];
if (this._firstNode.isSourceType()) {
this._tableNodeModel = this._firstNode.getTableModel();
}
this._onChange = _.debounce(this._onChange.bind(this), 500);
if (this.isNew()) {
// Bind change event in order to "store" all changed columns after creation
this._bindChangeEvent();
}
},
isNew: function () {
return !this.has('cartodb_id');
},
isPoint: function () {
return this._isType(TYPES_POINT);
},
isPolygon: function () {
return this._isType(TYPES_POLYGON);
},
isLine: function () {
return this._isType(TYPES_LINE);
},
_isType: function (type) {
return this._getType() === type;
},
isEditable: function () {
var analysisDefinitionModel = this._getAnalysisDefinitionNodeModel();
return !analysisDefinitionModel.isReadOnly();
},
_getPermissionModel: function () {
return this._tableNodeModel && this._tableNodeModel.getPermissionModel();
},
isReadOnly: function () {
return this._tableNodeModel && this._tableNodeModel.isReadOnly(this._userModel);
},
hasAnalyses: function () {
return this._layerDefinitionModel.hasAnalyses();
},
isCustomQueryApplied: function () {
var analysisDefinitionModel = this._getAnalysisDefinitionNodeModel();
return analysisDefinitionModel.isCustomQueryApplied();
},
_getAnalysisDefinitionNodeModel: function () {
return this._layerDefinitionModel.getAnalysisDefinitionNodeModel();
},
isEqual: function (featureDefinition) {
return this.get('cartodb_id') === featureDefinition.get('cartodb_id') &&
this.getLayerId() === featureDefinition.getLayerId();
},
getLayerId: function () {
return this._layerDefinitionModel.id;
},
getLayerDefinition: function () {
return this._layerDefinitionModel;
},
_cleanChangesHistory: function () {
this._changesHistory = [];
},
_bindChangeEvent: function () {
this.on('change', this._onChange, this);
},
_unbindChangeEvent: function () {
this.off('change', this._onChange, this);
},
_onChange: function () {
_.each(this.changed, function (value, key) {
if (!_.contains(this._changesHistory, key)) {
this._changesHistory.push(key);
}
}, this);
},
hasBeenChangedAfterLastSaved: function (key) {
return _.contains(this._changesHistory, key);
},
getFeatureType: function () {
if (this.isPoint()) {
return 'point';
}
if (this.isLine()) {
return 'line';
}
if (this.isPolygon()) {
return 'polygon';
}
},
fetch: function (options) {
options = options || {};
this._unbindChangeEvent();
this._getQueryRowModel().fetch({
success: function (data) {
this.set(data.toJSON());
// Bind change event in order to "store" all changed columns after starting edition
this._bindChangeEvent();
options.success && options.success();
}.bind(this)
});
},
save: function (options) {
options = options || {};
var columns = this._layerDefinitionModel.getColumnNamesFromSchema();
var attrs = _.pick(this.toJSON(), _.difference(columns, BLACKLISTED_COLUMNS));
this._getQueryRowModel().save(attrs, {
success: function (queryRowModel) {
if (this.isNew()) {
this.set('cartodb_id', queryRowModel.get('cartodb_id'));
}
this.trigger('save', this, options);
options.success && options.success();
this._cleanChangesHistory();
}.bind(this),
error: function () {
options.error && options.error();
}
});
},
destroy: function (options) {
options = options || {};
this._getQueryRowModel().destroy({
success: function () {
this.trigger('remove', this, options);
options.success && options.success();
}.bind(this),
error: function () {
options.error && options.error();
}
});
},
_getQueryRowModel: function () {
var attrs = {};
if (this.has('cartodb_id')) {
attrs.cartodb_id = this.get('cartodb_id');
}
this._queryRowModel = this._queryRowModel || new QueryRowModel(attrs, {
tableName: this._layerDefinitionModel.getTableName(),
configModel: this._configModel,
permissionModel: this._getPermissionModel(),
userModel: this._userModel
});
return this._queryRowModel;
},
_getType: function () {
var the_geom = this.get('the_geom');
var type = the_geom && convertGeoJSONTypeToFeatureType(the_geom) || this._featureType;
return type;
}
});
module.exports = FeatureDefinitionModel;