Initial commit
This commit is contained in:
+474
@@ -0,0 +1,474 @@
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var PanelWithOptionsView = require('builder/components/view-options/panel-with-options-view');
|
||||
var StyleContentView = require('./style-content-view');
|
||||
var StyleCartoCSSView = require('./style-cartocss-view');
|
||||
var ScrollView = require('builder/components/scroll/scroll-view');
|
||||
var TabPaneView = require('builder/components/tab-pane/tab-pane-view');
|
||||
var TabPaneCollection = require('builder/components/tab-pane/tab-pane-collection');
|
||||
var Toggler = require('builder/components/toggler/toggler-view');
|
||||
var UndoButtons = require('builder/components/undo-redo/undo-redo-view');
|
||||
var ParserCSS = require('builder/helpers/parser-css');
|
||||
var Infobox = require('builder/components/infobox/infobox-factory');
|
||||
var InfoboxModel = require('builder/components/infobox/infobox-model');
|
||||
var InfoboxCollection = require('builder/components/infobox/infobox-collection');
|
||||
var Notifier = require('builder/components/notifier/notifier');
|
||||
var CartoCSSNotifications = require('builder/cartocss-notifications');
|
||||
var MetricsTracker = require('builder/components/metrics/metrics-tracker');
|
||||
var MetricsTypes = require('builder/components/metrics/metrics-types');
|
||||
|
||||
var OnboardingLauncher = require('builder/components/onboardings/generic/generic-onboarding-launcher');
|
||||
var OnboardingView = require('builder/components/onboardings/layers/style-onboarding/style-onboarding-view');
|
||||
var checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
var ONBOARDING_KEY = 'layer-style-onboarding';
|
||||
|
||||
var REQUIRED_OPTS = [
|
||||
'layerDefinitionsCollection',
|
||||
'layerDefinitionModel',
|
||||
'userActions',
|
||||
'queryGeometryModel',
|
||||
'querySchemaModel',
|
||||
'queryRowsCollection',
|
||||
'modals',
|
||||
'editorModel',
|
||||
'configModel',
|
||||
'userModel',
|
||||
'onboardings',
|
||||
'onboardingNotification',
|
||||
'layerContentModel'
|
||||
];
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
|
||||
this._styleModel = this._layerDefinitionModel.styleModel;
|
||||
this._cartocssModel = this._layerDefinitionModel.cartocssModel;
|
||||
this._codemirrorModel = new Backbone.Model({
|
||||
content: this._layerDefinitionModel.get('cartocss')
|
||||
});
|
||||
|
||||
// Set edition attribute in case custom cartocss is applied
|
||||
this._editorModel.set({
|
||||
edition: !!this._layerDefinitionModel.get('cartocss_custom'),
|
||||
disabled: false
|
||||
});
|
||||
|
||||
this._infoboxModel = new InfoboxModel({
|
||||
state: this._isLayerHidden() ? 'layer-hidden' : ''
|
||||
});
|
||||
|
||||
this._overlayModel = new Backbone.Model({
|
||||
visible: this._isLayerHidden()
|
||||
});
|
||||
|
||||
this._applyButtonStatusModel = new Backbone.Model({
|
||||
loading: false
|
||||
});
|
||||
|
||||
this._togglerModel = new Backbone.Model({
|
||||
labels: [_t('editor.style.style-toggle.values'), _t('editor.style.style-toggle.cartocss')],
|
||||
active: this._editorModel.isEditing(),
|
||||
disabled: this._editorModel.isDisabled(),
|
||||
isDisableable: true,
|
||||
tooltip: _t('editor.style.style-toggle.tooltip')
|
||||
});
|
||||
|
||||
this._appendMapsAPIError();
|
||||
|
||||
CartoCSSNotifications.track(this);
|
||||
|
||||
this._onboardingLauncher = new OnboardingLauncher({
|
||||
view: OnboardingView,
|
||||
onboardingNotification: this._onboardingNotification,
|
||||
notificationKey: ONBOARDING_KEY,
|
||||
onboardings: this._onboardings
|
||||
}, {
|
||||
editorModel: this._editorModel,
|
||||
selector: 'LayerOnboarding'
|
||||
});
|
||||
|
||||
this._configPanes();
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this._launchOnboarding();
|
||||
this.clearSubViews();
|
||||
this.$el.empty();
|
||||
|
||||
this._initViews();
|
||||
this._infoboxState();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_launchOnboarding: function () {
|
||||
if (this._onboardingNotification.getKey(ONBOARDING_KEY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var georeferencePromise = this._layerDefinitionModel.canBeGeoreferenced();
|
||||
var hasGeomPromise = this._queryGeometryModel.hasValueAsync();
|
||||
var launchOnboarding = function (canBeGeoreferenced, hasGeom) {
|
||||
if (!this._editorModel.isEditing() && !canBeGeoreferenced && hasGeom) {
|
||||
this._onboardingLauncher.launch({
|
||||
geom: this._queryGeometryModel.get('simple_geom'),
|
||||
type: this._styleModel.get('type')
|
||||
});
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
Promise.all([georeferencePromise, hasGeomPromise])
|
||||
.then(function (values) {
|
||||
launchOnboarding(values[0], values[1]);
|
||||
});
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._layerDefinitionModel, 'change:error', this._appendMapsAPIError);
|
||||
this.listenTo(this._layerDefinitionModel, 'change:cartocss', this._onCartocssChanged);
|
||||
this.listenTo(this._layerDefinitionModel, 'change:visible', this._infoboxState);
|
||||
this.listenTo(this._layerDefinitionModel, 'change:autoStyle', this._infoboxState);
|
||||
|
||||
this.listenTo(this._editorModel, 'change:edition', this._onChangeEdition);
|
||||
this.listenTo(this._editorModel, 'change:disabled', this._onChangeDisabled);
|
||||
this.listenTo(this._togglerModel, 'change:active', this._onTogglerChanged);
|
||||
|
||||
this.listenTo(this._querySchemaModel, 'change:query_errors', this._updateEditor);
|
||||
|
||||
this.listenTo(this._styleModel, 'change', this._onCartocssChanged);
|
||||
this.listenTo(this._cartocssModel, 'undo redo', this._onUndoRedo);
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
var self = this;
|
||||
|
||||
var infoboxSstates = [
|
||||
{
|
||||
state: 'confirm',
|
||||
createContentView: function () {
|
||||
return Infobox.createWithAction({
|
||||
type: 'alert',
|
||||
title: _t('editor.style.messages.cartocss-applied.title'),
|
||||
body: _t('editor.style.messages.cartocss-applied.body'),
|
||||
action: {
|
||||
label: _t('editor.style.messages.cartocss-applied.clear')
|
||||
}
|
||||
});
|
||||
},
|
||||
onAction: self._clearCustomStyles.bind(self),
|
||||
onClose: self._cancelClearStyles.bind(self)
|
||||
}, {
|
||||
state: 'layer-hidden',
|
||||
createContentView: function () {
|
||||
return Infobox.createWithAction({
|
||||
type: self._layerDefinitionModel.get('cartocss_custom') ? 'code' : 'alert',
|
||||
title: _t('editor.messages.layer-hidden.title'),
|
||||
body: _t('editor.messages.layer-hidden.body'),
|
||||
action: {
|
||||
label: _t('editor.messages.layer-hidden.show')
|
||||
}
|
||||
});
|
||||
},
|
||||
onAction: self._showHiddenLayer.bind(self)
|
||||
}, {
|
||||
state: 'torque-exists',
|
||||
createContentView: function () {
|
||||
return Infobox.createWithAction({
|
||||
type: 'alert',
|
||||
title: _t('editor.style.messages.torque-exists.title'),
|
||||
body: _t('editor.style.messages.torque-exists.body'),
|
||||
action: {
|
||||
label: _t('editor.style.messages.torque-exists.continue')
|
||||
}
|
||||
});
|
||||
},
|
||||
onAction: self._applyTorqueAggregation.bind(self),
|
||||
onClose: self._cancelTorqueAggregation.bind(self)
|
||||
}
|
||||
];
|
||||
|
||||
var infoboxCollection = new InfoboxCollection(infoboxSstates);
|
||||
|
||||
var panelWithOptionsView = new PanelWithOptionsView({
|
||||
className: 'Editor-content',
|
||||
editorModel: self._editorModel,
|
||||
infoboxModel: self._infoboxModel,
|
||||
infoboxCollection: infoboxCollection,
|
||||
createContentView: function () {
|
||||
return new TabPaneView({
|
||||
collection: self._collectionPane
|
||||
});
|
||||
},
|
||||
createControlView: function () {
|
||||
return new Toggler({
|
||||
model: self._togglerModel
|
||||
});
|
||||
},
|
||||
createActionView: function () {
|
||||
return new TabPaneView({
|
||||
collection: self._collectionPane,
|
||||
createContentKey: 'createActionView'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.$el.append(panelWithOptionsView.render().el);
|
||||
this.addView(panelWithOptionsView);
|
||||
},
|
||||
|
||||
_onCartocssChanged: function () {
|
||||
this._codemirrorModel.set('content', this._layerDefinitionModel.get('cartocss'));
|
||||
},
|
||||
|
||||
_onUndoRedo: function () {
|
||||
this._codemirrorModel.set('content', this._cartocssModel.get('content'));
|
||||
},
|
||||
|
||||
_appendMapsAPIError: function () {
|
||||
var error = this._layerDefinitionModel.get('error');
|
||||
if (error) {
|
||||
if (error.subtype === 'turbo-carto') {
|
||||
var newErrors = _.clone(this._codemirrorModel.get('errors')) || [];
|
||||
newErrors.push({ line: error.line, message: error.message });
|
||||
this._codemirrorModel.set('errors', newErrors);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_updateEditor: function (model) {
|
||||
var errors = this._querySchemaModel.get('query_errors');
|
||||
var hasErrors = errors && errors.length > 0;
|
||||
this._editorModel.set('disabled', hasErrors);
|
||||
},
|
||||
|
||||
_saveCartoCSS: function (cb) {
|
||||
var content = this._codemirrorModel.get('content');
|
||||
var parser = new ParserCSS(content);
|
||||
var errors = parser.errors();
|
||||
|
||||
if (!content) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._applyButtonStatusModel.set('loading', true);
|
||||
this._codemirrorModel.set('errors', parser.parseError(errors));
|
||||
|
||||
if (errors.length === 0) {
|
||||
this._cartocssModel.set('content', content);
|
||||
|
||||
// Disable auto-style before saving, in order to not reset styles
|
||||
this._layerDefinitionModel.set('autoStyle', false);
|
||||
|
||||
this._layerDefinitionModel.save({
|
||||
cartocss_custom: true,
|
||||
cartocss: content
|
||||
}, {
|
||||
complete: cb
|
||||
});
|
||||
|
||||
MetricsTracker.track(MetricsTypes.APPLIED_CARTOCSS, {
|
||||
layer_id: this._layerDefinitionModel.get('id'),
|
||||
cartocss: this._layerDefinitionModel.get('cartocss')
|
||||
});
|
||||
|
||||
MetricsTracker.track(MetricsTypes.USED_ADVANCED_MODE, {
|
||||
mode_type: 'cartocss'
|
||||
});
|
||||
} else {
|
||||
this._editorModel.get('edition') === false && CartoCSSNotifications.showErrorNotification(parser.parseError(errors));
|
||||
this._applyButtonStatusModel.set('loading', false);
|
||||
}
|
||||
},
|
||||
|
||||
_onSaveComplete: function () {
|
||||
CartoCSSNotifications.showSuccessNotification();
|
||||
this._applyButtonStatusModel.set('loading', false);
|
||||
},
|
||||
|
||||
_cancelClearStyles: function () {
|
||||
this._infoboxModel.set({ state: '' });
|
||||
this._overlayModel.set({ visible: false });
|
||||
|
||||
this._editorModel.set({
|
||||
edition: true
|
||||
});
|
||||
},
|
||||
|
||||
_clearCustomStyles: function () {
|
||||
this._layerDefinitionModel.set('cartocss_custom', false);
|
||||
this._styleModel.applyLastState();
|
||||
this._infoboxModel.set({ state: '' });
|
||||
this._overlayModel.set({ visible: false });
|
||||
this.render();
|
||||
},
|
||||
|
||||
_cancelTorqueAggregation: function () {
|
||||
this._styleModel.applyLastState();
|
||||
this._infoboxModel.set({ state: '' });
|
||||
this._overlayModel.set({ visible: false });
|
||||
this.render();
|
||||
},
|
||||
|
||||
_applyTorqueAggregation: function () {
|
||||
if (this._layerDefinitionsCollection.isThereAnyTorqueLayer()) {
|
||||
var torqueLayer = this._layerDefinitionsCollection.findWhere({ type: 'torque' });
|
||||
torqueLayer.styleModel.setDefaultPropertiesByType('simple', 'point');
|
||||
}
|
||||
|
||||
this._infoboxModel.set({ state: 'unfreeze' });
|
||||
},
|
||||
|
||||
_onChangeEdition: function () {
|
||||
this._infoboxState();
|
||||
|
||||
var edition = this._editorModel.get('edition');
|
||||
var index = edition ? 1 : 0;
|
||||
this._collectionPane.at(index).set({ selected: true });
|
||||
this._togglerModel.set({ active: edition });
|
||||
},
|
||||
|
||||
_onChangeDisabled: function () {
|
||||
var disabled = this._editorModel.get('disabled');
|
||||
this._togglerModel.set({ disabled: disabled });
|
||||
},
|
||||
|
||||
_onTogglerChanged: function () {
|
||||
var checked = this._togglerModel.get('active');
|
||||
this._editorModel.set({ edition: checked });
|
||||
},
|
||||
|
||||
_freezeTorgeAggregation: function (styleType, currentGeometryType) {
|
||||
this._infoboxModel.set({ state: 'torque-exists' });
|
||||
this._overlayModel.set({ visible: true });
|
||||
|
||||
// Apply the previously selected style
|
||||
this._infoboxModel.once('change:state', function (mdl, state) {
|
||||
if (state === 'unfreeze') {
|
||||
this._moveTorqueLayerToTop(function () {
|
||||
this._overlayModel.set({ visible: false });
|
||||
this._styleModel.setDefaultPropertiesByType(styleType, currentGeometryType);
|
||||
}.bind(this));
|
||||
this._infoboxModel.set({ state: '' });
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
_moveTorqueLayerToTop: function (callback) {
|
||||
var notification = Notifier.addNotification({
|
||||
status: 'loading',
|
||||
info: _t('editor.layers.moveTorqueLayer.loading'),
|
||||
closable: true
|
||||
});
|
||||
|
||||
this._layerDefinitionsCollection.once('layerMoved', function () {
|
||||
callback && callback();
|
||||
notification.set({
|
||||
status: 'success',
|
||||
info: _t('editor.layers.moveTorqueLayer.success'),
|
||||
delay: Notifier.DEFAULT_DELAY
|
||||
});
|
||||
}, this);
|
||||
|
||||
this._userActions.moveLayer({
|
||||
from: this._layerDefinitionModel.get('order'),
|
||||
to: this._layerDefinitionsCollection.getTopDataLayerIndex()
|
||||
});
|
||||
},
|
||||
|
||||
_configPanes: function () {
|
||||
var self = this;
|
||||
var tabPaneTabs = [{
|
||||
selected: !this._layerDefinitionModel.get('cartocss_custom'),
|
||||
createContentView: function () {
|
||||
return new ScrollView({
|
||||
createContentView: function () {
|
||||
return new StyleContentView({
|
||||
className: 'Editor-content',
|
||||
userActions: self._userActions,
|
||||
layerDefinitionsCollection: self._layerDefinitionsCollection,
|
||||
layerDefinitionModel: self._layerDefinitionModel,
|
||||
styleModel: self._styleModel,
|
||||
modals: self._modals,
|
||||
configModel: self._configModel,
|
||||
userModel: self._userModel,
|
||||
queryGeometryModel: self._queryGeometryModel,
|
||||
querySchemaModel: self._querySchemaModel,
|
||||
editorModel: self._editorModel,
|
||||
overlayModel: self._overlayModel,
|
||||
freezeTorgeAggregation: self._freezeTorgeAggregation.bind(self),
|
||||
layerContentModel: self._layerContentModel
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
createActionView: function () {
|
||||
return new UndoButtons({
|
||||
trackModel: self._styleModel,
|
||||
editorModel: self._editorModel,
|
||||
applyButton: false
|
||||
});
|
||||
}
|
||||
}, {
|
||||
selected: this._layerDefinitionModel.get('cartocss_custom'),
|
||||
createContentView: function () {
|
||||
return new StyleCartoCSSView({
|
||||
layerDefinitionModel: self._layerDefinitionModel,
|
||||
querySchemaModel: self._querySchemaModel,
|
||||
styleModel: self._styleModel,
|
||||
editorModel: self._editorModel,
|
||||
codemirrorModel: self._codemirrorModel,
|
||||
onApplyEvent: self._saveCartoCSS.bind(self, self._onSaveComplete.bind(self)),
|
||||
overlayModel: self._overlayModel
|
||||
});
|
||||
},
|
||||
createActionView: function () {
|
||||
return new UndoButtons({
|
||||
trackModel: self._cartocssModel,
|
||||
editorModel: self._editorModel,
|
||||
applyStatusModel: self._applyButtonStatusModel,
|
||||
applyButton: true,
|
||||
onApplyClick: self._saveCartoCSS.bind(self, self._onSaveComplete.bind(self)),
|
||||
overlayModel: self._overlayModel
|
||||
});
|
||||
}
|
||||
}];
|
||||
|
||||
this._collectionPane = new TabPaneCollection(tabPaneTabs);
|
||||
},
|
||||
|
||||
_isLayerHidden: function () {
|
||||
return this._layerDefinitionModel.get('visible') === false;
|
||||
},
|
||||
|
||||
_infoboxState: function () {
|
||||
var edition = this._editorModel.get('edition');
|
||||
var cartocss_custom = this._layerDefinitionModel.get('cartocss_custom');
|
||||
var isAutoStyleApplied = this._layerDefinitionModel.get('autoStyle');
|
||||
|
||||
if (!edition && cartocss_custom && !isAutoStyleApplied) {
|
||||
this._infoboxModel.set({ state: 'confirm' });
|
||||
this._overlayModel.set({ visible: true });
|
||||
} else if (this._isLayerHidden()) {
|
||||
this._infoboxModel.set({ state: 'layer-hidden' });
|
||||
this._overlayModel.set({ visible: true });
|
||||
this._togglerModel.set({ disabled: true });
|
||||
} else {
|
||||
this._infoboxModel.set({ state: '' });
|
||||
this._overlayModel.set({ visible: false });
|
||||
this._togglerModel.set({ disabled: false });
|
||||
}
|
||||
},
|
||||
|
||||
_showHiddenLayer: function () {
|
||||
var savingOptions = {
|
||||
shouldPreserveAutoStyle: true
|
||||
};
|
||||
this._layerDefinitionModel.toggleVisible();
|
||||
this._userActions.saveLayer(this._layerDefinitionModel, savingOptions);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user