404 lines
12 KiB
JavaScript
404 lines
12 KiB
JavaScript
|
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);
|
||
|
}
|
||
|
});
|