Initial commit
This commit is contained in:
248
lib/assets/javascripts/builder/editor/layers/layers-view.js
Executable file
248
lib/assets/javascripts/builder/editor/layers/layers-view.js
Executable file
@@ -0,0 +1,248 @@
|
||||
require('jquery-ui');
|
||||
var _ = require('underscore');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var Notifier = require('builder/components/notifier/notifier');
|
||||
var template = require('./layers.tpl');
|
||||
var LayerViewFactory = require('./layer-view-factory');
|
||||
var IconView = require('builder/components/icon/icon-view');
|
||||
var checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view');
|
||||
var AddLayerView = require('builder/components/modals/add-layer/add-layer-view');
|
||||
var AddLayerModel = require('builder/components/modals/add-layer/add-layer-model');
|
||||
|
||||
var SORTABLE_SELECTOR = '.js-layers';
|
||||
var SORTABLE_ITEMS_SELECTOR = '.js-layer.js-sortable-item';
|
||||
|
||||
var BASEMAPS_SELECTOR = '.js-basemaps';
|
||||
|
||||
var REQUIRED_OPTS = [
|
||||
'analysisDefinitionNodesCollection',
|
||||
'layerDefinitionsCollection',
|
||||
'modals',
|
||||
'userModel',
|
||||
'configModel',
|
||||
'pollingModel',
|
||||
'editorModel',
|
||||
'userActions',
|
||||
'stateDefinitionModel',
|
||||
'visDefinitionModel',
|
||||
'widgetDefinitionsCollection',
|
||||
'showMaxLayerError',
|
||||
'onNotificationCloseAction'
|
||||
];
|
||||
|
||||
/**
|
||||
* View to render layer definitions list
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
events: {
|
||||
'click .js-add': '_addLayer'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||||
|
||||
this._layerViewFactory = new LayerViewFactory({
|
||||
userActions: this._userActions,
|
||||
layerDefinitionsCollection: this._layerDefinitionsCollection,
|
||||
analysisDefinitionNodesCollection: opts.analysisDefinitionNodesCollection,
|
||||
modals: opts.modals,
|
||||
configModel: opts.configModel,
|
||||
sortableSelector: SORTABLE_SELECTOR,
|
||||
stateDefinitionModel: this._stateDefinitionModel,
|
||||
visDefinitionModel: this._visDefinitionModel,
|
||||
widgetDefinitionsCollection: this._widgetDefinitionsCollection
|
||||
});
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._layerDefinitionsCollection, 'add remove change:id', this.render);
|
||||
this.listenTo(this._layerDefinitionsCollection, 'reset', this._updateAddButtonState);
|
||||
this.listenTo(this._layerDefinitionsCollection, 'add', this._createNotification);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
this.$el.html(template);
|
||||
|
||||
_.each(this._layerDefinitionsCollection.toArray().reverse(), this._addLayerView, this);
|
||||
this._initSortable();
|
||||
this._updateAddButtonState();
|
||||
this._initViews();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
var tooltip = new TipsyTooltipView({
|
||||
el: this.$('.js-add'),
|
||||
gravity: 'w',
|
||||
title: function () {
|
||||
return this._tooltipTitle;
|
||||
}.bind(this),
|
||||
offset: 8
|
||||
});
|
||||
this.addView(tooltip);
|
||||
|
||||
var plusIcon = new IconView({
|
||||
placeholder: this.$el.find('.js-plus-icon'),
|
||||
icon: 'plus'
|
||||
});
|
||||
plusIcon.render();
|
||||
this.addView(plusIcon);
|
||||
},
|
||||
|
||||
_addLayer: function () {
|
||||
if (this.$('.js-add').hasClass('is-disabled')) return;
|
||||
|
||||
var self = this;
|
||||
var modal = this._modals.create(function (modalModel) {
|
||||
var addLayerModel = new AddLayerModel({}, {
|
||||
userModel: self._userModel,
|
||||
userActions: self._userActions,
|
||||
configModel: self._configModel,
|
||||
pollingModel: self._pollingModel
|
||||
});
|
||||
|
||||
return new AddLayerView({
|
||||
modalModel: modalModel,
|
||||
configModel: self._configModel,
|
||||
userModel: self._userModel,
|
||||
createModel: addLayerModel,
|
||||
pollingModel: self._pollingModel
|
||||
});
|
||||
});
|
||||
modal.show();
|
||||
},
|
||||
|
||||
_createNotification: function (layerDefinitionModel) {
|
||||
var LAYER_ADDED_NOTIFICATION = 'layer-added';
|
||||
var notification = Notifier.getNotification(LAYER_ADDED_NOTIFICATION);
|
||||
|
||||
var notificationAttrs = {
|
||||
status: 'success',
|
||||
info: _t('notifications.layer.added'),
|
||||
closable: true,
|
||||
delay: Notifier.DEFAULT_DELAY
|
||||
};
|
||||
|
||||
if (notification) {
|
||||
notification.set(notificationAttrs);
|
||||
} else {
|
||||
notification = Notifier.addNotification(_.extend(notificationAttrs, {
|
||||
id: LAYER_ADDED_NOTIFICATION
|
||||
}));
|
||||
}
|
||||
|
||||
if (notification) {
|
||||
notification.once('notification:close', this._onNotificationClose.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
_onNotificationClose: function () {
|
||||
this._onNotificationCloseAction();
|
||||
},
|
||||
|
||||
_addLayerView: function (model) {
|
||||
if (this._layerViewFactory.isLabelsLayer(model)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var view = this._layerViewFactory.createLayerView(model);
|
||||
view.$el.data('layerId', model.id);
|
||||
this.addView(view);
|
||||
if (this._layerViewFactory.isBasemapLayer(model)) {
|
||||
this.$(BASEMAPS_SELECTOR).append(view.render().el);
|
||||
} else {
|
||||
this.$(SORTABLE_SELECTOR).append(view.render().el);
|
||||
}
|
||||
},
|
||||
|
||||
_initSortable: function () {
|
||||
this.$(SORTABLE_SELECTOR).sortable({
|
||||
axis: 'y',
|
||||
tolerance: 'pointer',
|
||||
items: SORTABLE_ITEMS_SELECTOR,
|
||||
placeholder: 'Editor-ListLayer-item Editor-ListLayer-item--placeholder',
|
||||
containment: SORTABLE_SELECTOR,
|
||||
forceHelperSize: true,
|
||||
forcePlaceholderSize: true,
|
||||
update: this._onSortableUpdate.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
_getDataLayerCount: function () {
|
||||
return this._layerDefinitionsCollection.getNumberOfDataLayers();
|
||||
},
|
||||
|
||||
_getMaxCount: function () {
|
||||
return this._userModel.get('limits').max_layers;
|
||||
},
|
||||
|
||||
_updateAddButtonState: function () {
|
||||
var count = this._getDataLayerCount();
|
||||
var max = this._getMaxCount();
|
||||
|
||||
if (count === max) {
|
||||
this._disableAddButton();
|
||||
this._tooltipTitle = _t('editor.layers.max-layers-infowindow.title');
|
||||
} else {
|
||||
this._enableAddButton();
|
||||
this._tooltipTitle = _t('editor.layers.add-layer.tooltip');
|
||||
}
|
||||
},
|
||||
|
||||
_enableAddButton: function () {
|
||||
this.$('.js-add').removeClass('is-disabled');
|
||||
},
|
||||
|
||||
_disableAddButton: function () {
|
||||
this.$('.js-add').addClass('is-disabled');
|
||||
},
|
||||
|
||||
_onSortableUpdate: function (event, ui) {
|
||||
var $draggedLayerElement = ui.item;
|
||||
var numberOfLayers = this.$(SORTABLE_SELECTOR).children().length - 1; // -1: remove the non-added layer
|
||||
var numberOfBasemaps = this.$(BASEMAPS_SELECTOR).children().length;
|
||||
var newPosition = numberOfLayers + numberOfBasemaps - $draggedLayerElement.index();
|
||||
|
||||
var layerId = $draggedLayerElement.data('layerId');
|
||||
if (layerId) {
|
||||
var layerDefinitionModel = this._layerDefinitionsCollection.get(layerId);
|
||||
this._userActions.moveLayer({
|
||||
from: layerDefinitionModel.get('order'),
|
||||
to: newPosition
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var analysisNodeId = $draggedLayerElement.data('analysis-node-id');
|
||||
var fromLayerLetter = $draggedLayerElement.data('layer-letter');
|
||||
if (analysisNodeId) {
|
||||
try {
|
||||
this._userActions.createLayerForAnalysisNode(analysisNodeId, fromLayerLetter, { at: newPosition });
|
||||
} catch (err) {
|
||||
if (/max/.test(err.message)) {
|
||||
$draggedLayerElement.remove();
|
||||
this._showMaxLayerError();
|
||||
} else {
|
||||
throw err; // unknown err, let it bubble up
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_destroySortable: function () {
|
||||
if (this.$(SORTABLE_SELECTOR).data('ui-sortable')) {
|
||||
this.$(SORTABLE_SELECTOR).sortable('destroy');
|
||||
}
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
this._destroySortable();
|
||||
CoreView.prototype.clean.apply(this);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user