363 lines
9.9 KiB
JavaScript
363 lines
9.9 KiB
JavaScript
|
var $ = require('jquery');
|
||
|
var Backbone = require('backbone');
|
||
|
var CoreView = require('backbone/core-view');
|
||
|
var PrivacyDialogView = require('./privacy-dialog-view');
|
||
|
var PrivacyWarningView = require('builder/components/modals/privacy-warning/privacy-warning-view');
|
||
|
var PasswordDialogView = require('./password-dialog-view');
|
||
|
var TabPaneView = require('builder/components/tab-pane/tab-pane-view');
|
||
|
var TabPaneCollection = require('builder/components/tab-pane/tab-pane-collection');
|
||
|
var CustomListCollection = require('builder/components/custom-list/custom-list-collection');
|
||
|
var ModalsServiceModel = require('builder/components/modals/modals-service-model');
|
||
|
var template = require('./privacy-dropdown.tpl');
|
||
|
var templateTabPane = require('./tab-pane.tpl');
|
||
|
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view');
|
||
|
var VisDefinitionModel = require('builder/data/vis-definition-model');
|
||
|
var checkAndBuildOpts = require('builder/helpers/required-opts');
|
||
|
var ErrorDetailsView = require('builder/components/background-importer/error-details-view');
|
||
|
|
||
|
var ESCAPE_KEY_CODE = 27;
|
||
|
|
||
|
var REQUIRED_OPTS = [
|
||
|
'visDefinitionModel',
|
||
|
'userModel',
|
||
|
'privacyCollection',
|
||
|
'configModel',
|
||
|
'isOwner'
|
||
|
];
|
||
|
|
||
|
var PRIVACY_MAP = {
|
||
|
public: 'green',
|
||
|
link: 'orange',
|
||
|
password: 'orange-dark',
|
||
|
private: 'red'
|
||
|
};
|
||
|
|
||
|
module.exports = CoreView.extend({
|
||
|
|
||
|
events: {
|
||
|
'click .js-toggle': '_onToggleDialogClicked'
|
||
|
},
|
||
|
|
||
|
initialize: function (opts) {
|
||
|
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
||
|
|
||
|
if (this._visDefinitionModel.isVisualization() && !this.options.mapcapsCollection) {
|
||
|
throw new Error('mapcapsCollection is required for visualizations');
|
||
|
}
|
||
|
|
||
|
this._triggerElementID = 'toggle' + this.cid;
|
||
|
|
||
|
this._modals = new ModalsServiceModel();
|
||
|
this.model = new Backbone.Model({
|
||
|
privacy: opts.visDefinitionModel.get('privacy'),
|
||
|
state: 'show'
|
||
|
});
|
||
|
|
||
|
this._onEscapePressed = this._onEscapePressed.bind(this);
|
||
|
this._onDocumentElementClicked = this._onDocumentElementClicked.bind(this);
|
||
|
|
||
|
if (this.options.ownerName) {
|
||
|
this._ownerName = this.options.ownerName;
|
||
|
}
|
||
|
|
||
|
if (this.options.mapcapsCollection) {
|
||
|
this._mapcapsCollection = this.options.mapcapsCollection;
|
||
|
}
|
||
|
|
||
|
this._configPrivacyCollection();
|
||
|
this._configPanes();
|
||
|
this._initBinds();
|
||
|
},
|
||
|
|
||
|
render: function () {
|
||
|
var privacy = this.model.get('privacy');
|
||
|
if (this.model.get('state') === 'error') {
|
||
|
privacy = this.options.visDefinitionModel.get('privacy');
|
||
|
}
|
||
|
var cssClass = PRIVACY_MAP[privacy.toLowerCase()];
|
||
|
var canChangePrivacy = this._canChangePrivacy(privacy);
|
||
|
|
||
|
this.clearSubViews();
|
||
|
this._hideDialog();
|
||
|
this.$el.html(template({
|
||
|
privacy: privacy,
|
||
|
cssClass: cssClass,
|
||
|
isLoading: this.model.get('state') === 'loading',
|
||
|
isOwner: this._isOwner,
|
||
|
canChangePrivacy: canChangePrivacy
|
||
|
}));
|
||
|
this._initViews();
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
_canChangePrivacy: function (privacy) {
|
||
|
var isIndividualUser = this.options.userModel.isIndividualUser();
|
||
|
var isMap = this.options.visDefinitionModel.isVisualization();
|
||
|
var hasRemainingPublicMaps = this.options.userModel.hasRemainingPublicMaps();
|
||
|
if (isIndividualUser && isMap && !hasRemainingPublicMaps && privacy === 'PRIVATE') {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
},
|
||
|
|
||
|
_initBinds: function () {
|
||
|
this._customCollection.on('change:selected', function (menuItem) {
|
||
|
if (menuItem.get('disabled')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (menuItem.get('val') === 'password') {
|
||
|
this._showPasswordDialog();
|
||
|
} else {
|
||
|
this._onToggleDialogClicked();
|
||
|
this._setPrivacy(menuItem.get('val'));
|
||
|
}
|
||
|
}, this);
|
||
|
|
||
|
this.add_related_model(this._customCollection);
|
||
|
|
||
|
this.model.on('change:state', this.render, this);
|
||
|
this.add_related_model(this.model); // explicit
|
||
|
},
|
||
|
|
||
|
_makePrivacyDialog: function () {
|
||
|
return new PrivacyDialogView({
|
||
|
model: this.model,
|
||
|
collection: this._customCollection,
|
||
|
userModel: this._userModel,
|
||
|
configModel: this._configModel
|
||
|
});
|
||
|
},
|
||
|
|
||
|
_makePasswordDialog: function () {
|
||
|
return new PasswordDialogView({
|
||
|
onBack: this._showPrivacyDialog.bind(this),
|
||
|
onEdit: this._setPassword.bind(this)
|
||
|
});
|
||
|
},
|
||
|
|
||
|
_setPassword: function (password) {
|
||
|
if (password !== '') {
|
||
|
this._privacyCollection.passwordOption().set({
|
||
|
password: password
|
||
|
});
|
||
|
|
||
|
this.model.set({ password: password });
|
||
|
this._setPrivacy('password');
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_setPrivacy: function (privacyStatus) {
|
||
|
var newPrivacyStatus = privacyStatus.toUpperCase();
|
||
|
|
||
|
this.model.set(
|
||
|
{ privacy: newPrivacyStatus },
|
||
|
{ silent: true }
|
||
|
);
|
||
|
|
||
|
if (this._shouldShowPrivacyWarning(newPrivacyStatus)) {
|
||
|
this._checkPrivacyChange(
|
||
|
newPrivacyStatus,
|
||
|
this._savePrivacy.bind(this),
|
||
|
this._discardPrivacyChange.bind(this)
|
||
|
);
|
||
|
} else {
|
||
|
this._savePrivacy();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_savePrivacy: function () {
|
||
|
var self = this;
|
||
|
var vis = this._visDefinitionModel;
|
||
|
|
||
|
this.model.set({ state: 'loading' });
|
||
|
|
||
|
this._privacyCollection.searchByPrivacy(this.model.get('privacy'))
|
||
|
.saveToVis(vis, {
|
||
|
success: function () {
|
||
|
self.model.set({state: 'show'});
|
||
|
},
|
||
|
error: function (req, resp) {
|
||
|
if (resp.responseText.indexOf('over account public map quota') !== -1) {
|
||
|
self._modals.create(function () {
|
||
|
return new ErrorDetailsView({
|
||
|
error: { errorCode: 8007 },
|
||
|
userModel: self._userModel,
|
||
|
configModel: self._configModel
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
self.model.set({state: 'error'});
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
_checkPrivacyChange: function (newPrivacyStatus, confirmCallback, dismissCallback) {
|
||
|
var self = this;
|
||
|
|
||
|
this._modals.create(function (modalModel) {
|
||
|
return new PrivacyWarningView({
|
||
|
modalModel: modalModel,
|
||
|
privacyType: newPrivacyStatus,
|
||
|
type: self._visDefinitionModel.isVisualization() ? 'visualization' : 'dataset',
|
||
|
onConfirm: confirmCallback,
|
||
|
onDismiss: dismissCallback
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
|
||
|
_discardPrivacyChange: function () {
|
||
|
var previousPrivacy = this.model.previous('privacy');
|
||
|
|
||
|
this.model.set('privacy', previousPrivacy, { silent: true });
|
||
|
this.model.set('state', 'show');
|
||
|
},
|
||
|
|
||
|
_shouldShowPrivacyWarning: function (privacyStatus) {
|
||
|
if (!this._userModel.canSelectPremiumOptions(this._visDefinitionModel)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
var isPubliclyAvailable = VisDefinitionModel.isPubliclyAvailable(privacyStatus);
|
||
|
|
||
|
if (this._visDefinitionModel.isVisualization()) {
|
||
|
return !!this._mapcapsCollection.length && isPubliclyAvailable;
|
||
|
}
|
||
|
|
||
|
return isPubliclyAvailable;
|
||
|
},
|
||
|
|
||
|
_transformPrivacyOptions: function () {
|
||
|
return this._privacyCollection.map(function (item) {
|
||
|
return {
|
||
|
label: item.get('title'),
|
||
|
val: item.get('privacy').toLowerCase(),
|
||
|
disabled: item.get('disabled'),
|
||
|
selected: item.get('selected'),
|
||
|
renderOptions: {
|
||
|
cssClass: item.get('cssClass')
|
||
|
}
|
||
|
};
|
||
|
}).filter(Boolean);
|
||
|
},
|
||
|
|
||
|
_configPrivacyCollection: function () {
|
||
|
var models = this._transformPrivacyOptions();
|
||
|
this._customCollection = new CustomListCollection(models);
|
||
|
},
|
||
|
|
||
|
_configPanes: function () {
|
||
|
var self = this;
|
||
|
var tabPaneTabs = [{
|
||
|
createContentView: self._showNoneDialog
|
||
|
}, {
|
||
|
createContentView: self._makePrivacyDialog.bind(self)
|
||
|
}, {
|
||
|
createContentView: self._makePasswordDialog.bind(self)
|
||
|
}];
|
||
|
|
||
|
this._collectionPane = new TabPaneCollection(tabPaneTabs);
|
||
|
},
|
||
|
|
||
|
_showNoneDialog: function () {
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
_showPasswordDialog: function () {
|
||
|
this._collectionPane.at(2).set({selected: true});
|
||
|
},
|
||
|
|
||
|
_showPrivacyDialog: function () {
|
||
|
this._customCollection.each(function (m) {
|
||
|
m.set({selected: false}, {silent: true});
|
||
|
});
|
||
|
|
||
|
this._collectionPane.at(1).set({selected: true});
|
||
|
},
|
||
|
|
||
|
_onToggleDialogClicked: function () {
|
||
|
if (this._isDialogVisible()) {
|
||
|
this._hideDialog();
|
||
|
} else {
|
||
|
this._onMouseClick();
|
||
|
this._initDocumentBinds();
|
||
|
this._showPrivacyDialog();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_isDialogVisible: function () {
|
||
|
return this._collectionPane.at(0).get('selected') === false;
|
||
|
},
|
||
|
|
||
|
_hideDialog: function () {
|
||
|
this._destroyDocumentBinds();
|
||
|
this._collectionPane.at(0).set({selected: true});
|
||
|
},
|
||
|
|
||
|
_showDialog: function () {
|
||
|
this._showPrivacyDialog();
|
||
|
},
|
||
|
|
||
|
_initViews: function () {
|
||
|
var view = new TabPaneView({
|
||
|
collection: this._collectionPane,
|
||
|
template: templateTabPane,
|
||
|
mouseOverAction: this._onMouseClick.bind(this)
|
||
|
});
|
||
|
this.$('.js-dialog').append(view.render().$el);
|
||
|
this.addView(view);
|
||
|
|
||
|
this._privacyTooltip = new TipsyTooltipView({
|
||
|
el: this.$('.js-tooltip'),
|
||
|
gravity: 'w',
|
||
|
html: true,
|
||
|
title: function () {
|
||
|
return this._getPrivacyInfo();
|
||
|
}.bind(this)
|
||
|
});
|
||
|
this.addView(this._privacyTooltip);
|
||
|
},
|
||
|
|
||
|
_getPrivacyInfo: function () {
|
||
|
var privacyInfo = _t('change-privacy');
|
||
|
|
||
|
if (this._ownerName) {
|
||
|
privacyInfo = _t('dataset.privacy.info', { name: this._ownerName });
|
||
|
}
|
||
|
|
||
|
return privacyInfo;
|
||
|
},
|
||
|
|
||
|
_initDocumentBinds: function () {
|
||
|
$(document).on('keydown', this._onEscapePressed);
|
||
|
$(document).on('mousedown', this._onDocumentElementClicked);
|
||
|
},
|
||
|
|
||
|
_destroyDocumentBinds: function () {
|
||
|
$(document).off('keydown', this._onEscapePressed);
|
||
|
$(document).off('mousedown', this._onDocumentElementClicked);
|
||
|
},
|
||
|
|
||
|
_onEscapePressed: function (ev) {
|
||
|
if (ev.which === ESCAPE_KEY_CODE) {
|
||
|
this._hideDialog();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_onDocumentElementClicked: function (ev) {
|
||
|
var $el = $(ev.target);
|
||
|
if ($el.closest(this.$el).length === 0 && $el.closest($('#' + this._triggerElementID)).length === 0) {
|
||
|
this._hideDialog();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_onMouseClick: function () {
|
||
|
this._privacyTooltip.hideTipsy();
|
||
|
},
|
||
|
|
||
|
clean: function () {
|
||
|
this._destroyDocumentBinds();
|
||
|
CoreView.prototype.clean.apply(this);
|
||
|
}
|
||
|
});
|