249 lines
7.1 KiB
JavaScript
249 lines
7.1 KiB
JavaScript
|
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);
|
||
|
}
|
||
|
});
|