cartodb/lib/assets/javascripts/builder/editor/layers/edit-feature-content-view.js
2020-06-15 10:58:47 +08:00

404 lines
12 KiB
JavaScript
Executable File

var _ = require('underscore');
var $ = require('jquery');
var CoreView = require('backbone/core-view');
var template = require('./edit-feature-content.tpl');
var EditFeatureActionView = require('./edit-feature-content-views/edit-feature-action-view');
var EditFeatureControlView = require('./edit-feature-content-views/edit-feature-control-view');
var EditFeatureHeaderView = require('./edit-feature-content-views/edit-feature-header-view');
var VisTableModel = require('builder/data/visualization-table-model');
var EditFeatureInnerView = require('./edit-feature-content-views/edit-feature-inner-view');
var PanelWithOptionsView = require('builder/components/view-options/panel-with-options-view');
var ScrollView = require('builder/components/scroll/scroll-view');
var Notifier = require('builder/components/notifier/notifier');
var EditFeatureGeometryFormModel = require('./edit-feature-content-views/edit-feature-geometry-form-model');
var EditFeatureGeometryPointFormModel = require('./edit-feature-content-views/edit-feature-geometry-point-form-model');
var EditFeatureAttributesFormModel = require('./edit-feature-content-views/edit-feature-attributes-form-model');
var StyleHelper = require('builder/helpers/style');
var StyleConstants = require('builder/components/form-components/_constants/_style');
var StylesFactory = require('builder/editor/style/styles-factory');
var Router = require('builder/routes/router');
var NOTIFICATION_ID = 'editFeatureNotification';
var NOTIFICATION_ERROR_TEMPLATE = _.template("<span class='u-errorTextColor'><%- title %></span>");
var REQUIRED_OPTS = [
'stackLayoutModel',
'layerDefinitionModel',
'configModel',
'mapModeModel',
'editorModel',
'modals'
];
var GEOMETRY_TYPE = 'simple_geom';
module.exports = CoreView.extend({
className: 'Editor-content',
events: {
'click .js-back': 'cleanAndGoBack'
},
initialize: function (opts) {
_.each(REQUIRED_OPTS, function (item) {
if (opts[item] === undefined) throw new Error(item + ' is required');
this['_' + item] = opts[item];
}, this);
this._featureModel = this._mapModeModel.getFeatureDefinition();
this._tableName = '';
this._url = '';
this._editorModel.set({
edition: false
});
this._getTable();
this._initBinds();
},
render: function () {
this.clearSubViews();
this.$el.html(template());
this._initViews();
return this;
},
_initBinds: function () {
if (this._querySchemaModel.get('status') !== 'fetched') {
// status can be: fetched, unavailable, fetching
this._querySchemaModel.bind('change:status', this.render, this);
this._querySchemaModel.fetch();
}
this._queryGeometryModel.bind('change:' + GEOMETRY_TYPE, this._checkNewLayerGeometryTypeDefinition, this);
this.listenTo(this._editorModel, 'cancelPreviousEditions', this.clean);
this.listenTo(this._featureModel, 'updateFeature', this._updateForms);
this.listenTo(this._featureModel, 'destroyFeature', this._onDestroyFeature);
this.listenTo(this._featureModel, 'destroyFeatureSuccess', this._onDestroyFeatureSuccess);
this.listenTo(this._featureModel, 'destroyFeatureFailed', this._onDestroyFeatureFailed);
this.listenTo(this._featureModel, 'addFeature', this._onAddFeature);
this.listenTo(this._featureModel, 'saveFeature', this._onSaveFeature);
this.listenTo(this._featureModel, 'saveFeatureSuccess', this._onSaveFeatureSuccess);
this.listenTo(this._featureModel, 'saveFeatureFailed', this._onSaveFeatureFailed);
},
_initViews: function () {
if (this._featureModel.isNew()) {
this._addRow();
} else {
this._renderInfo();
}
},
_updateForms: function () {
this._updateGeometry();
this._attributesFormModel.trigger('updateFeature');
},
_updateGeometry: function () {
var geojson = null;
try {
geojson = JSON.parse(this._featureModel.get('the_geom'));
} catch (err) {
// if the geom is not a valid json value
}
var attrs;
if (this._featureModel.isPoint()) {
attrs = {
lng: geojson && geojson.coordinates[0],
lat: geojson && geojson.coordinates[1]
};
} else {
attrs = {
the_geom: this._featureModel.get('the_geom')
};
}
this._geometryFormModel.set(attrs);
this._geometryFormModel.trigger('updateFeature', attrs);
},
_addRow: function () {
this._renderInfo();
},
_renderInfo: function () {
this._renderHeader();
this._renderContent();
},
_renderHeader: function () {
if (this._headerView) {
this.removeView(this._headerView);
this._headerView.clean();
}
this._headerView = new EditFeatureHeaderView({
url: this._url,
tableName: this._tableName,
layerDefinitionModel: this._layerDefinitionModel,
model: this._featureModel,
modals: this._modals,
isNew: this._featureModel.isNew(),
backAction: this.cleanAndGoBack.bind(this)
});
this.addView(this._headerView);
this.$('.js-editFeatureHeader').html(this._headerView.render().el);
},
_renderContent: function () {
if (this._contentView) {
this.removeView(this._contentView);
this._contentView.clean();
}
var geojson = null;
try {
geojson = JSON.parse(this._featureModel.get('the_geom'));
} catch (err) {
// if the geom is not a valid json value
}
if (this._featureModel.isPoint()) {
this._geometryFormModel = new EditFeatureGeometryPointFormModel({
lng: geojson && geojson.coordinates[0],
lat: geojson && geojson.coordinates[1]
}, {
featureModel: this._featureModel
});
} else {
this._geometryFormModel = new EditFeatureGeometryFormModel({
the_geom: this._featureModel.get('the_geom')
}, {
featureModel: this._featureModel
});
}
this._attributesFormModel = new EditFeatureAttributesFormModel(this._featureModel.toJSON(), {
featureModel: this._featureModel,
columnsCollection: this._sourceNode.querySchemaModel.columnsCollection,
configModel: this._configModel,
nodeDefModel: this._layerDefinitionModel.getAnalysisDefinitionNodeModel()
});
this._contentView = new PanelWithOptionsView({
className: 'Editor-content',
editorModel: this._editorModel,
createContentView: function () {
return new ScrollView({
createContentView: function () {
return new EditFeatureInnerView({
featureModel: this._featureModel,
geometryFormModel: this._geometryFormModel,
attributesFormModel: this._attributesFormModel
});
}.bind(this)
});
}.bind(this),
createControlView: function () {
return new EditFeatureControlView();
},
createActionView: function () {
return new EditFeatureActionView({
model: this.model,
featureModel: this._featureModel,
geometryFormModel: this._geometryFormModel,
attributesFormModel: this._attributesFormModel
});
}.bind(this)
});
this.addView(this._contentView);
this.$('.js-editFeatureContent').html(this._contentView.render().el);
},
_onDestroyFeature: function () {
if (Notifier.getNotification(NOTIFICATION_ID)) {
Notifier.removeNotification(NOTIFICATION_ID);
}
this.notification = Notifier.addNotification({
id: NOTIFICATION_ID,
status: 'loading',
info: _t('notifications.edit-feature.destroy.loading'),
closable: false
});
},
_onDestroyFeatureSuccess: function () {
this._onUpdateFeature('destroy');
this.notification.set({
status: 'success',
info: _t('notifications.edit-feature.destroy.success'),
closable: true
});
var layerId = this._layerDefinitionModel.get('id');
Router.goToStyleTab(layerId);
},
_onDestroyFeatureFailed: function (mdl, error) {
this.notification.set({
status: 'error',
info: NOTIFICATION_ERROR_TEMPLATE({
title: _t('notifications.edit-feature.destroy.error')
}),
closable: true
});
},
_onAddFeature: function () {
if (Notifier.getNotification(NOTIFICATION_ID)) {
Notifier.removeNotification(NOTIFICATION_ID);
}
this.notification = Notifier.addNotification({
id: NOTIFICATION_ID,
status: 'loading',
info: _t('notifications.edit-feature.adding'),
closable: false
});
},
_onSaveFeature: function () {
if (Notifier.getNotification(NOTIFICATION_ID)) {
Notifier.removeNotification(NOTIFICATION_ID);
}
this.notification = Notifier.addNotification({
id: NOTIFICATION_ID,
status: 'loading',
info: _t('notifications.edit-feature.save.loading'),
closable: false
});
},
_onSaveFeatureSuccess: function (operation, model) {
this._onUpdateFeature(operation);
this._needReloadVis() && this._mapModeModel.trigger('reloadVis');
this.notification.set({
status: 'success',
info: _t('notifications.edit-feature.save.success'),
closable: true
});
Router.editFeature(model);
},
_checkNewLayerGeometryTypeDefinition: function (queryGeometryModel, currentGeometryType) {
var layerGeometryTypeHasBeenDefined = currentGeometryType && !(queryGeometryModel.previous(GEOMETRY_TYPE));
if (layerGeometryTypeHasBeenDefined) {
var defaultStyle = _.extend({ type: StyleConstants.Type.SIMPLE },
StylesFactory.getDefaultStyleAttrsByType(StyleConstants.Type.SIMPLE, currentGeometryType)
);
this._layerDefinitionModel.styleModel.set(defaultStyle);
}
},
_onSaveFeatureFailed: function (mdl, error) {
this.notification.set({
status: 'error',
info: NOTIFICATION_ERROR_TEMPLATE({
title: _t('notifications.edit-feature.save.error')
}),
closable: true
});
},
_onUpdateFeature: function (operation) {
var self = this;
this._queryGeometryModel.hasValueAsync()
.then(function (hasGeom) {
if (operation !== 'save' || !hasGeom) {
self._queryGeometryModel.resetFetch();
}
});
if (operation === 'add' || operation === 'destroy') {
this._rowsCollection.resetFetch();
}
},
_needReloadVis: function () {
var style = this._layerDefinitionModel.styleModel;
var color = StyleHelper.getColorAttribute(style);
var size = StyleHelper.getSizeAttribute(style);
var changed = _.keys(this._featureModel.changedAttributes());
return (color && _.contains(changed, color) || size && _.contains(changed, size));
},
_getTable: function () {
this._sourceNode = this._getSourceNode();
if (this._sourceNode) {
var tableName = this._sourceNode.get('table_name');
this._visTableModel = new VisTableModel({
id: tableName,
table: {
name: tableName
}
}, {
configModel: this._configModel
});
this._querySchemaModel = this._sourceNode.querySchemaModel;
this._queryGeometryModel = this._sourceNode.queryGeometryModel;
this._rowsCollection = this._sourceNode.queryRowsCollection;
}
if (this._visTableModel) {
var tableModel = this._visTableModel.getTableModel();
this._tableName = tableModel.getUnquotedName();
this._url = this._visTableModel && this._visTableModel.datasetURL();
}
},
_getSourceNode: function () {
var node = this._layerDefinitionModel.getAnalysisDefinitionNodeModel();
var source;
if (node.get('type') === 'source') {
source = node;
} else {
var primarySource = node.getPrimarySource();
if (primarySource && primarySource.get('type') === 'source') {
source = primarySource;
}
}
return source;
},
_destroyContextOverlay: function () {
$('.js-editOverlay').fadeOut(200, function () {
$('.js-editOverlay').remove();
});
},
cleanAndGoBack: function () {
this.clean();
this._mapModeModel.enterViewingMode();
Router.goToPreviousRoute({
options: { replace: true }
});
},
clean: function () {
this._destroyContextOverlay();
CoreView.prototype.clean.apply(this);
}
});