Initial commit
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
<div class="u-flex u-justifyCenter">
|
||||
<div class="Modal-inner Modal-inner--grid u-flex u-justifyCenter">
|
||||
<div class="Modal-icon">
|
||||
<svg width="24px" height="25px" viewbox="521 436 24 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<path d="M524.5,440 L540.5,440 L540.5,460 L524.5,460 L524.5,440 Z M528.5,437 L536.5,437 L536.5,440 L528.5,440 L528.5,437 Z M522,440 L544,440 L522,440 Z M528.5,443.5 L528.5,455.5 L528.5,443.5 Z M532.5,443.5 L532.5,455.5 L532.5,443.5 Z M536.5,443.5 L536.5,455.5 L536.5,443.5 Z" id="Shape" stroke="#F19243" stroke-width="1" fill="none"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class=" CDB-Text CDB-Size-huge is-light u-bSpace--xl"><%- _t('components.modals.edit-feature.delete.title') %></h2>
|
||||
<p class="CDB-Text CDB-Size-large u-altTextColor"><%- _t('components.modals.edit-feature.delete.desc') %></p>
|
||||
<ul class="Modal-listActions u-flex u-alignCenter">
|
||||
<li class="Modal-listActionsitem">
|
||||
<button class="CDB-Button CDB-Button--secondary CDB-Button--big js-cancel">
|
||||
<span class="CDB-Button-Text CDB-Text is-semibold CDB-Size-medium u-upperCase">
|
||||
<%- _t('components.modals.edit-feature.delete.cancel') %>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="Modal-listActionsitem">
|
||||
<button class="CDB-Button CDB-Button--primary CDB-Button--big js-confirm">
|
||||
<span class="CDB-Button-Text CDB-Text is-semibold CDB-Size-medium u-upperCase">
|
||||
<%- _t('components.modals.edit-feature.delete.confirm') %>
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./edit-feature-action.tpl');
|
||||
|
||||
/**
|
||||
* View representing the apply button for a form
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
events: {
|
||||
'click .js-save': '_onSaveClicked'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.featureModel) throw new Error('featureModel is required');
|
||||
if (!opts.geometryFormModel) throw new Error('geometryFormModel is required');
|
||||
if (!opts.attributesFormModel) throw new Error('attributesFormModel is required');
|
||||
|
||||
this._featureModel = opts.featureModel;
|
||||
this._geometryFormModel = opts.geometryFormModel;
|
||||
this._attributesFormModel = opts.attributesFormModel;
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
this.$el.html(template({
|
||||
label: this._featureModel.isNew() ? _t('editor.edit-feature.add') : _t('editor.edit-feature.save'),
|
||||
isDisabled: !this._canSave()
|
||||
}));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.model.on('change', this.render, this);
|
||||
this._featureModel.on('change', function () {
|
||||
this.model.set('hasChanges', true);
|
||||
}, this);
|
||||
this.add_related_model(this._featureModel);
|
||||
this._geometryFormModel.bind('validate', function (isValid) {
|
||||
this.model.set('isValidGeometry', !isValid);
|
||||
}, this);
|
||||
this.add_related_model(this._geometryFormModel);
|
||||
this._attributesFormModel.bind('validate', function (isValid) {
|
||||
this.model.set('isValidAttributes', !isValid);
|
||||
}, this);
|
||||
this.add_related_model(this._attributesFormModel);
|
||||
},
|
||||
|
||||
_canSave: function () {
|
||||
var hasChanges = this.model.get('hasChanges');
|
||||
var isValidGeometry = this.model.get('isValidGeometry');
|
||||
var isValidAttributes = this.model.get('isValidAttributes');
|
||||
|
||||
return isValidGeometry && isValidAttributes && hasChanges;
|
||||
},
|
||||
|
||||
_onSaveClicked: function () {
|
||||
if (this._canSave()) {
|
||||
this._saveFeature();
|
||||
}
|
||||
},
|
||||
|
||||
_saveFeature: function () {
|
||||
var self = this;
|
||||
|
||||
var operation = this._featureModel.isNew() ? 'add' : 'save';
|
||||
var event = operation + 'Feature';
|
||||
this._featureModel.trigger(event);
|
||||
|
||||
this._featureModel.save({
|
||||
success: function () {
|
||||
self._featureModel.trigger('saveFeatureSuccess', operation, self._featureModel);
|
||||
self.model.set('hasChanges', false);
|
||||
},
|
||||
error: function () {
|
||||
self._featureModel.trigger('saveFeatureFailed');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
<button class="CDB-Button CDB-Button--primary js-save <% if (isDisabled) { %>is-disabled<% } %>">
|
||||
<span class="CDB-Button-Text CDB-Text is-semibold CDB-Size-small u-upperCase">
|
||||
<%- label %>
|
||||
</span>
|
||||
</button>
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var ColumnRowData = require('builder/data/column-row-data');
|
||||
var DialogConstants = require('builder/components/form-components/_constants/_dialogs');
|
||||
var checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
var FIELDTYPE_TO_FORMTYPE = {
|
||||
string: 'Text',
|
||||
boolean: 'Radio',
|
||||
number: 'Number',
|
||||
date: 'DateTime',
|
||||
geometry: 'Text'
|
||||
};
|
||||
|
||||
var BLACKLISTED_COLUMNS = ['created_at', 'the_geom', 'the_geom_webmercator', 'updated_at'];
|
||||
|
||||
var REQUIRED_OPTS = [
|
||||
'featureModel',
|
||||
'columnsCollection',
|
||||
'configModel',
|
||||
'nodeDefModel'
|
||||
];
|
||||
|
||||
module.exports = Backbone.Model.extend({
|
||||
|
||||
initialize: function (attrs, opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
this._generateSchema();
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.bind('change', this._onChange, this);
|
||||
},
|
||||
|
||||
_onChange: function () {
|
||||
_.each(this.changed, function (val, key) {
|
||||
this._featureModel.set(key, val);
|
||||
}, this);
|
||||
},
|
||||
|
||||
_getInputType: function (columnRowData) {
|
||||
var rows = columnRowData.getRows();
|
||||
return rows && rows.length ? 'Suggest' : 'Text';
|
||||
},
|
||||
|
||||
_getSupportedColumnType: function (columnType) {
|
||||
var supportedColumnType = _.find(_.keys(FIELDTYPE_TO_FORMTYPE), function (fieldType) {
|
||||
return fieldType === columnType;
|
||||
});
|
||||
|
||||
return supportedColumnType || 'string';
|
||||
},
|
||||
|
||||
_generateSchema: function () {
|
||||
var self = this;
|
||||
|
||||
this.schema = {};
|
||||
|
||||
this._columnsCollection.each(function (model) {
|
||||
var columnName = model.get('name');
|
||||
var columnType = this._getSupportedColumnType(model.get('type'));
|
||||
|
||||
if (!_.contains(BLACKLISTED_COLUMNS, columnName)) {
|
||||
// default field type
|
||||
this.schema[columnName] = {
|
||||
type: FIELDTYPE_TO_FORMTYPE[columnType]
|
||||
};
|
||||
|
||||
if (columnType === 'date') {
|
||||
this.schema[columnName].dialogMode = DialogConstants.Mode.FLOAT;
|
||||
}
|
||||
|
||||
if (columnType === 'string') {
|
||||
var columnRowData = new ColumnRowData({
|
||||
column: columnName
|
||||
}, {
|
||||
nodeDefModel: this._nodeDefModel,
|
||||
configModel: this._configModel
|
||||
});
|
||||
columnRowData.bind('columnsFetched', function (rows) {
|
||||
var type = self._getInputType(this);
|
||||
if (self.schema[columnName].type !== type) {
|
||||
self.schema[columnName].type = type;
|
||||
if (type === 'Suggest') {
|
||||
self.schema[columnName].dialogMode = DialogConstants.Mode.FLOAT;
|
||||
}
|
||||
self.schema[columnName].editorAttrs = {
|
||||
showSearch: true,
|
||||
defaultValue: true,
|
||||
allowFreeTextInput: true,
|
||||
collectionData: rows
|
||||
};
|
||||
|
||||
self._onChangeSchema();
|
||||
}
|
||||
});
|
||||
columnRowData.fetch();
|
||||
}
|
||||
|
||||
if (columnType === 'number') {
|
||||
this.schema[columnName].isFormatted = true;
|
||||
this.schema[columnName].showSlider = false;
|
||||
}
|
||||
|
||||
if (columnType === 'boolean') {
|
||||
this.schema[columnName].options = [
|
||||
{
|
||||
label: _t('form-components.editors.radio.true'),
|
||||
val: true
|
||||
}, {
|
||||
label: _t('form-components.editors.radio.false'),
|
||||
val: false
|
||||
}, {
|
||||
label: _t('form-components.editors.radio.null'),
|
||||
val: null
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
if (columnName === 'cartodb_id') {
|
||||
this.schema[columnName].isFormatted = false;
|
||||
this.schema[columnName].editorAttrs = {
|
||||
disabled: true
|
||||
};
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
_onChangeSchema: function () {
|
||||
this.trigger('changeSchema');
|
||||
}
|
||||
|
||||
});
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./edit-feature-attributes-form.tpl');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
module: 'editor:layers:edit-feature-content-views:edit-feature-attributes-form-view',
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this.$el.html(template());
|
||||
|
||||
this._generateForms();
|
||||
|
||||
this.model.bind('changeSchema', this._generateForms, this);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_generateForms: function () {
|
||||
var self = this;
|
||||
|
||||
if (this._formView) {
|
||||
this._formView.remove();
|
||||
}
|
||||
|
||||
this._formView = new Backbone.Form({
|
||||
model: this.model
|
||||
});
|
||||
|
||||
this._formView.bind('change', function () {
|
||||
var validate = this.validate();
|
||||
self.model.trigger('validate', !!validate);
|
||||
|
||||
if (!validate) {
|
||||
this.commit();
|
||||
}
|
||||
});
|
||||
|
||||
this.$('.js-form').append(this._formView.render().$el);
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
if (this._formView) {
|
||||
this._formView.remove();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<div class="Editor-HeaderInfo">
|
||||
<div class="Editor-HeaderNumeration CDB-Text is-semibold u-rSpace--m">2</div>
|
||||
|
||||
<div class="Editor-HeaderInfo-inner CDB-Text">
|
||||
<div class="Editor-HeaderInfo-title u-bSpace--m">
|
||||
<h2 class="CDB-Text CDB-HeaderInfo-titleText CDB-Size-large"><%- _t('editor.edit-feature.attributes') %></h2>
|
||||
</div>
|
||||
<p class="CDB-Text u-upperCase CDB-FontSize-small u-altTextColor u-bSpace--m"><%- _t('editor.edit-feature.attributes-columns') %></p>
|
||||
<div class="js-form"></div>
|
||||
</div>
|
||||
</div>
|
||||
lib/assets/javascripts/builder/editor/layers/edit-feature-content-views/edit-feature-control-view.js
Executable
+12
@@ -0,0 +1,12 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./edit-feature-control.tpl');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
render: function () {
|
||||
this.$el.html(template());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
<button class="CDB-Button u-upperCase js-back">
|
||||
<span class="CDB-Button-Text CDB-Text is-semibold CDB-Size-small u-actionTextColor"><%- _t('editor.edit-feature.cancel') %></span>
|
||||
</button>
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var cdb = require('internal-carto.js');
|
||||
|
||||
module.exports = Backbone.Model.extend({
|
||||
|
||||
_COORDINATES_OPTIONS: {
|
||||
min_lat: -90,
|
||||
max_lat: 90,
|
||||
min_lng: -180,
|
||||
max_lng: 180
|
||||
},
|
||||
|
||||
initialize: function (attrs, opts) {
|
||||
if (!opts.featureModel) throw new Error('featureModel is required');
|
||||
|
||||
this._featureModel = opts.featureModel;
|
||||
|
||||
this._generateSchema();
|
||||
},
|
||||
|
||||
_formatCoordinate: function (coordinate) {
|
||||
if (this._isValidCoordinate(coordinate)) {
|
||||
return parseFloat(parseFloat(coordinate).toFixed(8));
|
||||
}
|
||||
},
|
||||
|
||||
_isValidCoordinate: function (coordinate) {
|
||||
return _.isNumber(coordinate) || _.isString(coordinate);
|
||||
},
|
||||
|
||||
_getLatitude: function (pos) {
|
||||
return pos && pos[0];
|
||||
},
|
||||
|
||||
_getLongitude: function (pos) {
|
||||
return pos && pos[1];
|
||||
},
|
||||
|
||||
_validateGeom: function (value) {
|
||||
var validation;
|
||||
var coordinates;
|
||||
|
||||
var geoJSON = JSON.parse(value);
|
||||
|
||||
if (this._featureModel.isLine()) {
|
||||
coordinates = cdb.helpers.GeoJSONHelper.getPolylineLatLngsFromGeoJSONCoords(geoJSON);
|
||||
} else {
|
||||
coordinates = cdb.helpers.GeoJSONHelper.getPolygonLatLngsFromGeoJSONCoords(geoJSON);
|
||||
}
|
||||
|
||||
var errors = _.chain(coordinates)
|
||||
.reduce(function (memo, coordinate) {
|
||||
var latitude = this._formatCoordinate(this._getLatitude(coordinate));
|
||||
var longitude = this._formatCoordinate(this._getLongitude(coordinate));
|
||||
|
||||
var latError = (latitude > this._COORDINATES_OPTIONS.max_lat || latitude < this._COORDINATES_OPTIONS.min_lat);
|
||||
|
||||
if (latError) {
|
||||
memo.push(_t('editor.edit-feature.out-of-bounds-lat'));
|
||||
}
|
||||
|
||||
var lngError = (longitude > this._COORDINATES_OPTIONS.max_lng || longitude < this._COORDINATES_OPTIONS.min_lng);
|
||||
|
||||
if (lngError) {
|
||||
memo.push(_t('editor.edit-feature.out-of-bounds-lng'));
|
||||
}
|
||||
|
||||
return memo;
|
||||
}, [], this)
|
||||
.uniq()
|
||||
.value();
|
||||
|
||||
if (errors.length) {
|
||||
validation = {
|
||||
message: errors.join(' ')
|
||||
};
|
||||
}
|
||||
|
||||
return validation;
|
||||
},
|
||||
|
||||
_generateSchema: function () {
|
||||
this.schema = {};
|
||||
|
||||
this.schema.the_geom = {
|
||||
type: 'Text',
|
||||
validators: ['required', this._validateGeom.bind(this)],
|
||||
editorAttrs: {
|
||||
disabled: true
|
||||
},
|
||||
hasCopyButton: this._featureModel.has('the_geom')
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./edit-feature-geometry-form.tpl');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this.$el.html(template());
|
||||
|
||||
this._generateForms();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_generateForms: function () {
|
||||
if (this._formView) {
|
||||
this._formView.remove();
|
||||
}
|
||||
|
||||
this._formView = new Backbone.Form({
|
||||
model: this.model
|
||||
});
|
||||
|
||||
this._formView.bind('change', this._validateForm, this);
|
||||
|
||||
this.model.bind('updateFeature', function (attrs) {
|
||||
_.each(attrs, function (value, key) {
|
||||
this._formView.fields[key].editor.setValue(value);
|
||||
}, this);
|
||||
this._validateForm();
|
||||
}, this);
|
||||
|
||||
this.$('.js-form').append(this._formView.render().$el);
|
||||
},
|
||||
|
||||
_validateForm: function () {
|
||||
var validate = this._formView.validate();
|
||||
this.model.trigger('validate', !!validate);
|
||||
|
||||
if (!validate) {
|
||||
this._formView.commit();
|
||||
}
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
if (this._formView) {
|
||||
this._formView.remove();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<div class="Editor-HeaderInfo">
|
||||
<div class="Editor-HeaderNumeration CDB-Text is-semibold u-rSpace--m">1</div>
|
||||
<div class="Editor-HeaderInfo-inner CDB-Text">
|
||||
<div class="Editor-HeaderInfo-title u-bSpace--m">
|
||||
<h2 class="CDB-Text CDB-HeaderInfo-titleText CDB-Size-large"><%- _t('editor.edit-feature.geometry') %></h2>
|
||||
</div>
|
||||
<p class="CDB-Text u-upperCase CDB-FontSize-small u-altTextColor u-bSpace--m"><%- _t('editor.edit-feature.geometry-edit') %></p>
|
||||
<div class="js-form"></div>
|
||||
</div>
|
||||
</div>
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
var _ = require('underscore');
|
||||
var EditFeatureGeometryFormModel = require('./edit-feature-geometry-form-model');
|
||||
|
||||
var getCoordinatesFromGeoJSON = function (geoJSON) {
|
||||
if (geoJSON && geoJSON.coordinates && geoJSON.coordinates.length === 2) {
|
||||
return geoJSON.coordinates;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = EditFeatureGeometryFormModel.extend({
|
||||
|
||||
initialize: function () {
|
||||
EditFeatureGeometryFormModel.prototype.initialize.apply(this, arguments);
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.bind('change:lat', this._onLatLngChange, this);
|
||||
this.bind('change:lng', this._onLatLngChange, this);
|
||||
},
|
||||
|
||||
_onLatLngChange: function () {
|
||||
var newGeoJSON = this._toGeoJSON();
|
||||
var currentGeoJSON = {};
|
||||
|
||||
if (this._featureModel.get('the_geom')) {
|
||||
currentGeoJSON = JSON.parse(this._featureModel.get('the_geom'));
|
||||
}
|
||||
|
||||
// Only set `the_geom` if there's new geoJSON
|
||||
if (!_.isEqual(newGeoJSON, currentGeoJSON)) {
|
||||
this._featureModel.set('the_geom', JSON.stringify(newGeoJSON));
|
||||
}
|
||||
},
|
||||
|
||||
_toGeoJSON: function () {
|
||||
var latitude = this._formatCoordinate(this._getLatitude());
|
||||
var longitude = this._formatCoordinate(this._getLongitude());
|
||||
if (this._isValidCoordinate(latitude) && this._isValidCoordinate(longitude)) {
|
||||
return {
|
||||
'type': 'Point',
|
||||
'coordinates': [ longitude, latitude ]
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
_getLatitude: function () {
|
||||
if (this.has('lat')) {
|
||||
return this.get('lat');
|
||||
}
|
||||
|
||||
var geoJSON = JSON.parse(this._featureModel.get('the_geom'));
|
||||
var geoJSONCoordinates = getCoordinatesFromGeoJSON(geoJSON);
|
||||
var latitudeFromGeoJSON = geoJSONCoordinates && geoJSONCoordinates[1];
|
||||
if (latitudeFromGeoJSON) {
|
||||
return latitudeFromGeoJSON;
|
||||
}
|
||||
},
|
||||
|
||||
_getLongitude: function () {
|
||||
if (this.has('lng')) {
|
||||
return this.get('lng');
|
||||
}
|
||||
|
||||
var geoJSON = JSON.parse(this._featureModel.get('the_geom'));
|
||||
var geoJSONCoordinates = getCoordinatesFromGeoJSON(geoJSON);
|
||||
var longitudeFromGeoJSON = geoJSONCoordinates && geoJSONCoordinates[1];
|
||||
if (longitudeFromGeoJSON) {
|
||||
return longitudeFromGeoJSON;
|
||||
}
|
||||
},
|
||||
|
||||
_validateLatitude: function (value, formValues) {
|
||||
var numericValue = +value;
|
||||
|
||||
var error = {
|
||||
message: _t('editor.edit-feature.valid-lat')
|
||||
};
|
||||
|
||||
if (_.isNumber(numericValue) &&
|
||||
(numericValue >= this._COORDINATES_OPTIONS.min_lat && numericValue <= this._COORDINATES_OPTIONS.max_lat)) {
|
||||
return null; // valid latitude
|
||||
}
|
||||
|
||||
if (_.isNumber(numericValue) &&
|
||||
(numericValue > this._COORDINATES_OPTIONS.max_lat || numericValue < this._COORDINATES_OPTIONS.min_lat)) {
|
||||
error.message = _t('editor.edit-feature.out-of-bounds-lat');
|
||||
}
|
||||
|
||||
return error;
|
||||
},
|
||||
|
||||
_validateLongitude: function (value, formValues) {
|
||||
var numericValue = +value;
|
||||
|
||||
var error = {
|
||||
message: _t('editor.edit-feature.valid-lng')
|
||||
};
|
||||
|
||||
if (_.isNumber(numericValue) &&
|
||||
(numericValue >= this._COORDINATES_OPTIONS.min_lng && numericValue <= this._COORDINATES_OPTIONS.max_lng)) {
|
||||
return null; // valid longitude
|
||||
}
|
||||
|
||||
if (_.isNumber(numericValue) &&
|
||||
(numericValue > this._COORDINATES_OPTIONS.max_lng || numericValue < this._COORDINATES_OPTIONS.min_lng)) {
|
||||
error.message = _t('editor.edit-feature.out-of-bounds-lng');
|
||||
}
|
||||
|
||||
return error;
|
||||
},
|
||||
|
||||
_generateSchema: function () {
|
||||
this.schema = {};
|
||||
|
||||
this.schema.lng = {
|
||||
type: 'Number',
|
||||
validators: ['required', this._validateLongitude.bind(this)],
|
||||
showSlider: false
|
||||
};
|
||||
|
||||
this.schema.lat = {
|
||||
type: 'Number',
|
||||
validators: ['required', this._validateLatitude.bind(this)],
|
||||
showSlider: false
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./edit-feature-header.tpl');
|
||||
var ContextMenuFactory = require('builder/components/context-menu-factory-view');
|
||||
var ConfirmationView = require('builder/components/modals/confirmation/modal-confirmation-view');
|
||||
var checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
var templateConfirmation = require('./delete-feature-confirmation.tpl');
|
||||
|
||||
var REQUIRED_OPTS = [
|
||||
'url',
|
||||
'tableName',
|
||||
'modals',
|
||||
'isNew',
|
||||
'layerDefinitionModel'
|
||||
];
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
var letter = this._layerDefinitionModel.get('letter');
|
||||
var featureType = this.model.getFeatureType() ? _t('editor.edit-feature.features.' + this.model.getFeatureType()) : _t('editor.edit-feature.features.geometry');
|
||||
var breadcrumbLabel = this._isNew ? _t('editor.edit-feature.add-' + featureType) : _t('editor.edit-feature.edit', { featureType: featureType });
|
||||
|
||||
this.$el.html(
|
||||
template({
|
||||
url: this._url,
|
||||
layerName: this._layerDefinitionModel.getName(),
|
||||
tableName: this._tableName,
|
||||
bgColor: this._layerDefinitionModel.getColor(),
|
||||
letter: letter,
|
||||
featureType: featureType,
|
||||
breadcrumbLabel: breadcrumbLabel
|
||||
})
|
||||
);
|
||||
|
||||
if (!this._isNew) {
|
||||
this._initViews();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
var menuItems = [{
|
||||
label: _t('editor.edit-feature.delete', { featureType: _t('editor.edit-feature.features.' + this.model.getFeatureType()) }),
|
||||
val: 'delete-feature',
|
||||
destructive: true,
|
||||
action: this._confirmDeleteFeature.bind(this)
|
||||
}];
|
||||
|
||||
this._contextMenuFactory = new ContextMenuFactory({
|
||||
menuItems: menuItems
|
||||
});
|
||||
|
||||
this.$('.js-context-menu').append(this._contextMenuFactory.render().el);
|
||||
this.addView(this._contextMenuFactory);
|
||||
},
|
||||
|
||||
_confirmDeleteFeature: function () {
|
||||
this._modals.create(function (modalModel) {
|
||||
return new ConfirmationView({
|
||||
modalModel: modalModel,
|
||||
template: templateConfirmation,
|
||||
runAction: this._destroyFeature.bind(this)
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_destroyFeature: function () {
|
||||
this.model.trigger('destroyFeature');
|
||||
|
||||
this.model.destroy({
|
||||
success: function () {
|
||||
this.model.trigger('destroyFeatureSuccess');
|
||||
}.bind(this),
|
||||
error: function () {
|
||||
this.model.trigger('destroyFeatureFailed');
|
||||
}.bind(this)
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
<ul class="Editor-breadcrumb">
|
||||
<li class="Editor-breadcrumbItem CDB-Text CDB-Size-medium u-actionTextColor">
|
||||
<button class="js-back">
|
||||
<i class="CDB-IconFont CDB-IconFont-arrowPrev Size-large u-rSpace"></i>
|
||||
|
||||
<span class="Editor-breadcrumbLink"><%- _t('back') %></span>
|
||||
</button>
|
||||
</li>
|
||||
|
||||
<li class="Editor-breadcrumbItem CDB-Text CDB-Size-medium">
|
||||
<span class="Editor-breadcrumbSep"> / </span>
|
||||
<%- breadcrumbLabel %>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="Editor-HeaderInfoEditor Editor-HeaderInfoEditor--layer">
|
||||
<div class="Editor-HeaderInfo-inner Editor-HeaderInfo-inner--wide u-ellipsis">
|
||||
<div class="Editor-HeaderInfo-title u-bSpace">
|
||||
<span class="CDB-SelectorLayer-letter CDB-Text CDB-Size-small u-whiteTextColor u-tSpace--m u-rSpace--m u-upperCase" style="background-color: <%- bgColor %>;">
|
||||
<%- letter %>
|
||||
</span>
|
||||
|
||||
<h2 class="Inline-editor">
|
||||
<div class="CDB-Text CDB-Size-huge is-light u-ellipsis">
|
||||
<%- layerName %>
|
||||
</div>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="Editor-HeaderInfo-source u-flex">
|
||||
<p class="CDB-Text CDB-Size-small u-ellipsis">
|
||||
<a href="<%- url %>" target="_blank" title="<%- tableName %>" class="Editor-headerLayerName"><%- tableName %></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="u-flex u-tSpace-xl js-context-menu"></div>
|
||||
</div>
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var EditFeatureGeometryFormView = require('./edit-feature-geometry-form-view');
|
||||
var EditFeatureAttributesFormView = require('./edit-feature-attributes-form-view');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.featureModel) throw new Error('featureModel is required');
|
||||
if (!opts.geometryFormModel) throw new Error('geometryFormModel is required');
|
||||
if (!opts.attributesFormModel) throw new Error('attributesFormModel is required');
|
||||
|
||||
this._featureModel = opts.featureModel;
|
||||
this._geometryFormModel = opts.geometryFormModel;
|
||||
this._attributesFormModel = opts.attributesFormModel;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
if (this._editFeatureGeometryFormView) {
|
||||
this._editFeatureGeometryFormView.clean();
|
||||
}
|
||||
|
||||
if (this._editFeatureAttributesFormView) {
|
||||
this._editFeatureAttributesFormView.clean();
|
||||
}
|
||||
|
||||
this.clearSubViews();
|
||||
|
||||
this.$el.empty();
|
||||
|
||||
this._editFeatureGeometryFormView = new EditFeatureGeometryFormView({
|
||||
model: this._geometryFormModel
|
||||
});
|
||||
|
||||
this.addView(this._editFeatureGeometryFormView);
|
||||
this.$el.append(this._editFeatureGeometryFormView.render().el);
|
||||
|
||||
this._editFeatureAttributesFormView = new EditFeatureAttributesFormView({
|
||||
model: this._attributesFormModel
|
||||
});
|
||||
|
||||
this.addView(this._editFeatureAttributesFormView);
|
||||
this.$el.append(this._editFeatureAttributesFormView.render().el);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user