cartodb-4.42/lib/assets/javascripts/builder/components/modals/add-layer/content/navigation-view.js
2024-04-06 05:25:13 +00:00

230 lines
6.2 KiB
JavaScript
Executable File

var cdb = require('internal-carto.js');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var $ = require('jquery');
var _ = require('underscore');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var template = require('./navigation.tpl');
var REQUIRED_OPTS = [
'configModel',
'createModel',
'userModel',
'routerModel',
'tablesCollection'
];
/**
* Listing datasets navigation.
*
* - 'Filter by' datasets.
* - 'Search' any pattern within dataset collection.
*
*/
module.exports = CoreView.extend({
events: {
'submit .js-search-form': '_submitSearch',
'keydown .js-search-form': '_onSearchKeyDown',
'click .js-search-form': 'killEvent',
'click .js-search-link': '_onSearchClick',
'click .js-clean-search': '_onCleanSearchClick',
'click .js-shared': '_onSharedClick',
'click .js-library': '_onLibraryClick',
'click .js-connect': '_onConnectClick',
'click .js-upload': '_onUploadClick',
'click .js-datasets': '_onDatasetsClick',
'click .js-create-empty': '_onCreateEmptyClick'
},
initialize: function (opts) {
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
this.model = new Backbone.Model();
this._preRender();
this._initBinds();
},
// It is necessary to add two static elements because
// they can't be removed/replaced using render method
// each time a change (in a model or a collection) happens.
// This is due to the behaviour of the CSS animations.
_preRender: function () {
var $uInner = $('<div>').addClass('u-inner');
var $filtersInner = $('<div>').addClass('Filters-inner');
this.$el.append($uInner.append($filtersInner));
},
render: function (m, c) {
this.clearSubViews();
this.$('.Filters-inner').html(
template(
_.extend(
{
showDatasets: this._createModel.showDatasets(),
createModelType: this._createModel.get('type'),
canCreateDataset: this._userModel.canCreateDatasets(),
listingType: this._createModel.get('listing'),
isInsideOrg: this._userModel.isInsideOrg(),
totalShared: this._tablesCollection.getTotalStat('total_shared'),
selectedItemsCount: this._selectedItems().length,
hasDataLibrary: this._configModel.dataLibraryEnabled()
},
this._routerModel.attributes
)
)
);
this._animate();
if (this._routerModel.isSearching()) {
this._focusSearchInput();
}
return this;
},
_initBinds: function () {
this.listenTo(this.model, 'change:isSearchEnabled', this._onChangeIsSearchEnabled, this);
this.listenTo(this._createModel, 'change:listing', this.render, this);
this.listenTo(this._routerModel, 'change', this.render, this);
this.listenTo(this._tablesCollection, 'sync', this.render, this);
},
_onChangeIsSearchEnabled: function (model, isSearchEnabled) {
this._enableSearchUI(isSearchEnabled);
if (this._routerModel.isSearching()) {
this._cleanSearch();
} else if (isSearchEnabled) {
this._$searchInput().val('');
this._focusSearchInput();
}
},
_$searchInput: function () {
return this.$('.js-search-input');
},
_focusSearchInput: function () {
this._$searchInput()
.select()
.focus();
},
_onSearchKeyDown: function (e) {
if (e.keyCode === 27) { // ESC
this.killEvent(e);
this._cleanSearch();
}
},
_selectedItems: function () {
return this._tablesCollection.where({ selected: true });
},
_animate: function () {
this._enableSearchUI(!!this._routerModel.isSearching());
// Check if user doesn't have any table and it is in library section
// to remove useless shadow
var inLibrarySection = this._routerModel.get('library');
var inDatasetsSection = this._createModel.get('listing') === 'datasets';
var hasDatasets = this._tablesCollection.getTotalStat('total_user_entries') > 0;
this.$el.toggleClass('no-shadow', inLibrarySection && !hasDatasets && inDatasetsSection);
},
_enableSearchUI: function (enable) {
this.$('.js-search-field').toggle(enable);
this.$('.js-links-list').toggleClass('is-hidden', enable);
this.$('.js-order-list').toggleClass('is-hidden', enable);
},
_onDatasetsClick: function () {
this._routerModel.set({
shared: 'no',
library: false,
page: 1
});
this._routerModel.trigger('change', this._routerModel);
this._createModel.set('listing', 'datasets');
},
_onSharedClick: function () {
this._routerModel.set({
shared: 'only',
library: false,
page: 1
});
this._routerModel.trigger('change', this._routerModel);
this._createModel.set('listing', 'datasets');
},
_onLibraryClick: function () {
this._routerModel.set({
shared: 'no',
library: true,
page: 1
});
this._routerModel.trigger('change', this._routerModel);
this._createModel.set('listing', 'datasets');
},
_onConnectClick: function () {
if (this._userModel.canCreateDatasets()) {
this._createModel.set('listing', 'import');
}
},
_onUploadClick: function () {
if (this._userModel.canCreateDatasets()) {
this._createModel.set('listing', 'upload');
}
},
_onCreateEmptyClick: function () {
if (this._userModel.canCreateDatasets()) {
this._createModel.createFromScratch();
}
},
// Selection actions
_onSearchClick: function (e) {
this.killEvent(e);
this.model.set('isSearchEnabled', !this.model.get('isSearchEnabled'));
},
// Filter actions
_onCleanSearchClick: function (e) {
if (e) {
e.preventDefault();
}
this._cleanSearch();
},
_cleanSearch: function () {
this._routerModel.set({
q: '',
tag: '',
shared: 'no',
library: this._createModel.showLibrary()
});
this.model.set('isSearchEnabled', false);
},
_submitSearch: function (e) {
this.killEvent(e);
var val = cdb.core.sanitize.html(this.$('.js-search-input').val().trim());
var tag = val.search(':') === 0 ? val.replace(':', '') : '';
var q = val.search(':') !== 0 ? val : '';
this._routerModel.set({
page: 1,
tag: tag,
q: q,
shared: 'yes'
});
this._createModel.set('listing', 'datasets');
}
});