var $ = require('jquery'); var Backbone = require('backbone'); var _ = require('underscore'); var CoreView = require('backbone/core-view'); var createTextLabelsTabPaneRouted = require('builder/components/tab-pane/create-text-labels-tab-pane-routed'); var Header = require('./editor-header.js'); var EditorTabPaneTemplate = require('./editor-tab-pane.tpl'); var EditorWidgetsView = require('./widgets/widgets-view'); var LayersView = require('./layers/layers-view'); var ScrollView = require('builder/components/scroll/scroll-view'); var PanelWithOptionsView = require('builder/components/view-options/panel-with-options-view'); var ShareButtonView = require('./layers/share-button-view'); var PublishView = require('builder/components/modals/publish/publish-view'); var checkAndBuildOpts = require('builder/helpers/required-opts'); 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 AppNotifications = require('builder/app-notifications'); var zoomToData = require('./map-operations/zoom-to-data'); var Router = require('builder/routes/router'); var REQUIRED_OPTS = [ 'userActions', 'modals', 'configModel', 'userModel', 'editorModel', 'pollingModel', 'analysisDefinitionNodesCollection', 'layerDefinitionsCollection', 'privacyCollection', 'widgetDefinitionsCollection', 'mapcapsCollection', 'visDefinitionModel', 'stateDefinitionModel', 'selectedTabItem', 'mapStackLayoutModel', 'routeModel' ]; var LAYERS_TAB_NAME = 'layers'; var WIDGETS_TAB_NAME = 'widgets'; var MAX_LAYERS_REACHED = 'MAX_LAYERS_REACHED'; var ORIGIN_TABLE = 'table'; module.exports = CoreView.extend({ className: 'Editor-content', initialize: function (opts) { checkAndBuildOpts(opts, REQUIRED_OPTS, this); this._initModels(); this._initBinds(); this._zoomToData = zoomToData; // For using Dependency Injection in specs }, render: function () { var self = this; var count = this._getDataLayerCount(); var max = this._getMaxCount(); this.clearSubViews(); this.$el.empty(); var infoboxStates = [ this._getMaxLayerInfoBoxForCurrentUser(), this._getUnknownErrorInfobox(), this._getLimitInfobox('interactivity'), this._getLimitInfobox('limit') ]; this._infoboxModel = new InfoboxModel({ state: null }); var infoboxCollection = new InfoboxCollection(infoboxStates); var tabPaneTabs = [{ name: LAYERS_TAB_NAME, label: this._getTranslatedLayersLabel(count, max), selected: this._selectedTabItem === LAYERS_TAB_NAME, onClick: function () { Router.goToLayerList(); }, createContentView: function () { return new PanelWithOptionsView({ className: 'Editor-content js-editorPanelContent', editorModel: self._editorModel, infoboxModel: self._infoboxModel, infoboxCollection: infoboxCollection, createContentView: function () { return new ScrollView({ createContentView: function () { var scrollViewInstance = this; return new LayersView({ modals: self._modals, userModel: self._userModel, editorModel: self._editorModel, configModel: self._configModel, pollingModel: self._pollingModel, userActions: self._userActions, layerDefinitionsCollection: self._layerDefinitionsCollection, analysisDefinitionNodesCollection: self._analysisDefinitionNodesCollection, stateDefinitionModel: self._stateDefinitionModel, widgetDefinitionsCollection: self._widgetDefinitionsCollection, visDefinitionModel: self._visDefinitionModel, showMaxLayerError: self._infoboxState.bind(self), onNotificationCloseAction: scrollViewInstance._updateScrollWhenExist.bind(scrollViewInstance) }); } }); }, createActionView: function () { return new ShareButtonView({ visDefinitionModel: self._visDefinitionModel, onClickAction: self._share.bind(self) }); } }); } }, { name: 'widgets', label: _t('editor.tab-pane.widgets.title-label'), selected: this._selectedTabItem === WIDGETS_TAB_NAME, onClick: function () { Router.goToWidgetList(); }, createContentView: function () { return new PanelWithOptionsView({ className: 'Editor-content', editorModel: self._editorModel, infoboxModel: self._infoboxModel, infoboxCollection: infoboxCollection, createContentView: function () { return new ScrollView({ createContentView: function () { return new EditorWidgetsView({ userActions: self._userActions, modals: self._modals, layerDefinitionsCollection: self._layerDefinitionsCollection, widgetDefinitionsCollection: self._widgetDefinitionsCollection, analysisDefinitionNodesCollection: self._analysisDefinitionNodesCollection, userModel: self._userModel, configModel: self._configModel, stackLayoutModel: self._mapStackLayoutModel }); } }); }, createActionView: function () { return new ShareButtonView({ visDefinitionModel: self._visDefinitionModel, onClickAction: self._share.bind(self) }); } }); } }]; var header = new Header({ editorModel: self._editorModel, mapcapsCollection: self._mapcapsCollection, modals: self._modals, visDefinitionModel: self._visDefinitionModel, privacyCollection: self._privacyCollection, clickPrivacyAction: self._share.bind(self), onRemoveMap: self._onRemoveMap.bind(self), configModel: self._configModel, userModel: self._userModel }); header.bind('export-image', this._onExportImage, this); this.$el.append(header.render().$el); this.addView(header); var tabPaneOptions = { tabPaneOptions: { template: EditorTabPaneTemplate, tabPaneItemOptions: { tagName: 'li', klassName: 'CDB-NavMenu-item' } }, tabPaneItemLabelOptions: { tagName: 'button', className: 'CDB-NavMenu-link u-upperCase' } }; this._mapTabPaneView = createTextLabelsTabPaneRouted(tabPaneTabs, tabPaneOptions); this.$el.append(this._mapTabPaneView.render().$el); this.addView(this._mapTabPaneView); this._infoboxState(); return this; }, _initModels: function () { this._updatedModel = new Backbone.Model({ date: '' }); }, _initBinds: function () { this.listenTo(this._editorModel, 'change:edition', this._changeStyle); this.listenTo(this._layerDefinitionsCollection, 'add', this._onLayerAdd); this.listenTo(this._layerDefinitionsCollection, 'add remove', this._onLayerCountChange); this.listenTo(AppNotifications.getCollection(), 'add', this._infoboxState); this.listenTo(this._routeModel, 'change:currentRoute', this._handleRoute); }, _handleRoute: function (routeModel) { var currentRoute = routeModel.get('currentRoute'); if (!currentRoute) return; var routeName = currentRoute[0]; if (routeName === WIDGETS_TAB_NAME) { this._mapTabPaneView.setSelectedTabPaneByName(WIDGETS_TAB_NAME); } else { this._mapTabPaneView.setSelectedTabPaneByName(LAYERS_TAB_NAME); } }, _onLayerAdd: function (model, collection, options) { if (options.origin && options.origin === ORIGIN_TABLE) { var nodeModel = model.getAnalysisDefinitionNodeModel(); var query = nodeModel.querySchemaModel.get('query'); this._zoomToData(this._configModel, this._stateDefinitionModel, query); } this._visDefinitionModel.fetch(); }, _getMaxLayerTitle: function () { return _t('editor.layers.max-layers-infowindow.title'); }, _getMaxLayerInfoBoxForCurrentUser: function () { var infoboxOpts = { type: 'alert', title: this._getMaxLayerTitle() }; var baseState = { state: MAX_LAYERS_REACHED }; // Open-source / local installation if (this._configModel.isHosted()) { infoboxOpts.body = _t('editor.layers.max-layers-infowindow.custom.body', { maxLayers: this._getMaxCount() }); infoboxOpts.action = { label: _t('editor.layers.max-layers-infowindow.custom.contact') }; baseState.onAction = function () { window.open(_t('editor.layers.max-layers-infowindow.custom.contact-url')); }; } else { if (this._userModel.isInsideOrg()) { if (this._userModel.isOrgAdmin()) { infoboxOpts.body = _t('editor.layers.max-layers-infowindow.org-admin.body', { maxLayers: this._getMaxCount() }); infoboxOpts.action = { label: _t('editor.layers.max-layers-infowindow.org-admin.upgrade') }; } else { infoboxOpts.body = _t('editor.layers.max-layers-infowindow.org.body', { maxLayers: this._getMaxCount() }); infoboxOpts.action = { label: _t('editor.layers.max-layers-infowindow.org.upgrade') }; } baseState.onAction = function () { window.open('mailto:' + this._userModel.upgradeContactEmail()); }; } else { baseState.onAction = function () { window.open(_t('editor.layers.max-layers-infowindow.pricing')); }; infoboxOpts.body = _t('editor.layers.max-layers-infowindow.regular.body', { maxLayers: this._getMaxCount() }); infoboxOpts.action = { label: _t('editor.layers.max-layers-infowindow.regular.upgrade') }; } } return _.extend(baseState, { createContentView: function () { return Infobox.createWithAction(infoboxOpts); } }); }, _getUnknownErrorInfobox: function () { return { state: 'unknown', createContentView: function () { return Infobox.createWithAction({ type: 'alert', title: _t('editor.messages.generic-error.title'), body: _t('editor.messages.generic-error.body'), className: 'fs-unknown-tile-error' }); } }; }, _getLimitInfobox: function (type) { var infoboxOpts = { type: 'alert', title: _t('editor.messages.' + type + '.title'), body: _t('editor.messages.' + type + '.body') }; var baseState = { state: type, onClose: function () { AppNotifications.muteByType(type); this._infoboxModel.set('state', null); }.bind(this) }; if (!this._configModel.isHosted()) { infoboxOpts.action = { label: _t('editor.messages.' + type + '.cta.label'), type: 'secondary' }; baseState.onAction = function () { window.open(_t('editor.messages.' + type + '.cta.url')); }; infoboxOpts.body = _t('editor.messages.' + type + '.body') + _t('editor.messages.' + type + '.try_to'); } return _.extend(baseState, { createContentView: function () { return Infobox.createWithAction(infoboxOpts); } }); }, _onLayerCountChange: function () { var count = this._getDataLayerCount(); var max = this._getMaxCount(); var layersModel = this._mapTabPaneView.getTabPaneCollection().find(function (model) { return model.get('name') === LAYERS_TAB_NAME; }); layersModel.set('label', this._getTranslatedLayersLabel(count, max)); if (count === max) { this._infoboxState(); } else { this._infoboxModel.set('state', null); } }, _infoboxState: function () { var count = this._getDataLayerCount(); var max = this._getMaxCount(); var hasLimitError = AppNotifications.getByType('limit'); var hasUnknownError = AppNotifications.getByType('unknown'); var hasInteractivityError = AppNotifications.getByType('interactivity'); if (hasLimitError) { this._infoboxModel.set('state', 'limit'); } else if (hasInteractivityError) { this._infoboxModel.set('state', 'interactivity'); } else if (hasUnknownError) { this._infoboxModel.set('state', 'unknown'); } else if (count === max) { this._infoboxModel.set('state', MAX_LAYERS_REACHED); } else { this._infoboxModel.set('state', null); } }, _onExportImage: function () { this.trigger('export-image', this); }, _onRemoveMap: function () { window.location = this._userModel.get('base_url'); }, _getDataLayerCount: function () { return this._layerDefinitionsCollection.getNumberOfDataLayers(); }, _getMaxCount: function () { return this._userModel.get('limits').max_layers; }, _getTranslatedLayersLabel: function (count, max) { return _t('editor.tab-pane.layers.title-label', { count: count, maxCount: max }); }, _share: function () { var self = this; this._modals.create(function (modalModel) { return new PublishView({ mapcapsCollection: self._mapcapsCollection, modalModel: modalModel, visDefinitionModel: self._visDefinitionModel, privacyCollection: self._privacyCollection, userModel: self._userModel, configModel: self._configModel, isOwner: true }); }, { breadcrumbsEnabled: true }); }, _changeStyle: function (m) { this.$el.toggleClass('is-dark'); this._mapTabPaneView.changeStyleMenu(m); }, _setUpdateFromCreation: function () { this._updatedModel.set({date: this._visDefinitionModel.get('created_at')}); }, _setUpdateFromMapcap: function (mapcaps) { this._updatedModel.set({date: mapcaps[0].created_at}); }, _getMapcaps: function () { var updateFromCreation = this._setUpdateFromCreation.bind(this); var updateFromMapcap = this._setUpdateFromMapcap.bind(this); var url = this._visDefinitionModel.mapcapsURL(); var data = { api_key: this._configModel.get('api_key') }; $.get(url, data) .done(function (data) { if (data.length > 0) { updateFromMapcap(data); } else { updateFromCreation(); } }) .fail(function () { updateFromCreation(); }); } });