cartodb/lib/assets/javascripts/dashboard/components/dashboard-header-view.js
2020-06-15 10:58:47 +08:00

157 lines
4.6 KiB
JavaScript

const $ = require('jquery');
const CoreView = require('backbone/core-view');
const checkAndBuildOpts = require('builder/helpers/required-opts');
const logoTemplate = require('./dashboard-header/logo.tpl');
const dropdownLinkTemplate = require('./dashboard-header/breadcrumbs/dropdown-link.tpl');
const SettingsDropdownView = require('./dashboard-header/settings-dropdown-view');
const BreadcrumbsDropdown = require('./dashboard-header/breadcrumbs/dropdown-view');
const UserNotificationsView = require('./dashboard-header/notifications/user-notifications-view');
const REQUIRED_OPTS = [
'viewModel',
'configModel'
];
/**
* Responsible for the header part of the layout.
* It's currently pre-rendered server-side, why the header element is required to be given when instantiating the view.
*/
module.exports = CoreView.extend({
events: {
'click .js-breadcrumb-dropdown': '_createBreadcrumbsDropdown',
'click .js-settings-dropdown': '_createSettingsDropdown'
},
initialize: function (options) {
checkAndBuildOpts(options, REQUIRED_OPTS, this);
if (!this.options.el) {
throw new Error('el element is required');
}
this.router = this.options.router;
this._initBinds();
},
render: function () {
this.clearSubViews();
this._renderBreadcrumbsDropdownLink();
this._renderNotifications();
this._renderLogoLink();
return this;
},
_initBinds: function () {
this._viewModel.bind('change', this._renderBreadcrumbsDropdownLink, this);
this.listenTo(this._viewModel, 'change', this._renderBreadcrumbsDropdownLink);
if (this.router) {
this.listenTo(this.router.model, 'change', this._onRouterChange);
}
if (this.collection) {
this.listenTo(this.collection, 'reset', this._stopLogoAnimation);
this.listenTo(this.collection, 'error', this._onCollectionError);
}
},
_onCollectionError: function (col, e, opts) {
// Old requests can be stopped, so aborted requests are not
// considered as an error
if (!e || (e && e.statusText !== 'abort')) {
this._stopLogoAnimation();
}
},
// TODO: Not sure if the changes made here are correct, because of backbone version changes
_onRouterChange: function (m, c) {
if (m.changed && !m.changed.content_type && this.collection.total_user_entries > 0) {
this._startLogoAnimation();
}
},
_startLogoAnimation: function () {
this.$('.Logo').addClass('is-loading');
},
_stopLogoAnimation: function () {
this.$('.Logo').removeClass('is-loading');
},
_renderBreadcrumbsDropdownLink: function () {
this.$('.js-breadcrumb-dropdown').html(
dropdownLinkTemplate({
title: this._viewModel.breadcrumbTitle(),
dropdownEnabled: this._viewModel.isBreadcrumbDropdownEnabled()
})
);
},
_renderNotifications: function () {
var userNotifications = new UserNotificationsView({
user: this.model,
configModel: this._configModel,
organizationNotifications: this.options.organizationNotifications
});
this.$('.js-user-notifications').html(userNotifications.render().el);
this.addView(userNotifications);
},
_renderLogoLink: function () {
this.$('.js-logo').html(
logoTemplate({
homeUrl: this.model.viewUrl().dashboard(),
googleEnabled: this.model.featureEnabled('google_maps')
})
);
},
_createSettingsDropdown: function (event) {
this.killEvent(event);
this._setupDropdown(new SettingsDropdownView({
target: $(event.target),
model: this.model, // a user model
configModel: this._configModel,
horizontalOffset: 15
}));
},
_createBreadcrumbsDropdown: function (ev) {
if (this._viewModel.isBreadcrumbDropdownEnabled()) {
this.killEvent(ev);
this._setupDropdown(new BreadcrumbsDropdown({
target: $(ev.target),
model: this.model,
viewModel: this._viewModel,
router: this.router, // optional
tick: 'center',
template: require('dashboard/components/dashboard-header/breadcrumbs/dropdown.tpl'),
horizontalOffset: this.options.breadcrumbsDropdownOffset
}));
}
},
_setupDropdown: function (dropdownView) {
this._closeAnyOtherOpenDialogs();
this._previousDropDown = dropdownView;
this.addView(dropdownView);
dropdownView.on('onDropdownHidden', function () {
dropdownView.clean();
}, this);
dropdownView.render();
dropdownView.open();
},
_closeAnyOtherOpenDialogs: function () {
// TODO: This is not how it used to work, it used to listen to a global event
if (this._previousDropDown) {
this._previousDropDown.hide();
}
}
});