var CoreView = require('backbone/core-view'); var template = require('./dataset-header.tpl'); var moment = require('moment'); var InlineEditorView = require('builder/components/inline-editor/inline-editor-view'); var TipsyTooltipView = require('builder/components/tipsy-tooltip-view'); var renameTableOperation = require('builder/dataset/operations/table-rename-operation'); var templateInlineEditor = require('./inline-editor.tpl'); var ConfirmationModalView = require('builder/components/modals/confirmation/modal-confirmation-view'); var RemoveDatasetModalView = require('builder/components/modals/remove-dataset/remove-dataset-view'); var PublishView = require('builder/components/modals/publish/publish-view'); var PrivacyDropdown = require('builder/components/privacy-dropdown/privacy-dropdown-view'); var PrivacyCollection = require('builder/components/modals/publish/privacy-collection'); var CreatePrivacyOptions = require('builder/components/modals/publish/create-privacy-options'); var ShareWith = require('builder/components/modals/publish/share-with-view'); var CreationModalView = require('builder/components/modals/creation/modal-creation-view'); var EditMetadataView = require('builder/components/modals/dataset-metadata/dataset-metadata-view'); var VisTableModel = require('builder/data/visualization-table-model'); var templateConfirmation = require('./rename-confirmation-modal.tpl'); var createContextMenu = require('./create-context-menu'); var tableDuplicationOperation = require('builder/dataset/operations/table-duplication-operation'); var checkAndBuildOpts = require('builder/helpers/required-opts'); var TITLE_SUFFIX = ' | CARTO'; var PRIVACY_MAP = { public: 'green', link: 'orange', private: 'red' }; var REQUIRED_OPTS = [ 'analysisDefinitionNodeModel', 'configModel', 'layerDefinitionModel', 'modals', 'router', 'userModel', 'visModel' ]; module.exports = CoreView.extend({ className: 'Editor-HeaderInfoEditor', events: { 'click .js-options': '_showContextMenu' }, initialize: function (opts) { checkAndBuildOpts(opts, REQUIRED_OPTS, this); var privacyOptions = CreatePrivacyOptions(this._visModel, this._userModel); this._querySchemaModel = this._analysisDefinitionNodeModel.querySchemaModel; this._tableModel = this._analysisDefinitionNodeModel.getTableModel(); this._syncModel = this._tableModel.getSyncModel(); this._privacyCollection = new PrivacyCollection(privacyOptions); this._setDocumentTitle(); this._initBinds(); }, render: function () { this.clearSubViews(); var privacy = this._visModel.get('privacy'); this.$el.html( template({ title: this._tableModel.getUnqualifiedName(), privacy: privacy, isOwner: this._isDatasetOwner(), isCustomQueryApplied: this._isCustomQueryApplied(), isSync: this._tableModel.isSync(), syncState: this._syncModel.get('state'), cssClass: PRIVACY_MAP[privacy.toLowerCase()], ago: moment(this._visModel.get('updated_at')).fromNow(), avatar: this._userModel.get('avatar_url'), isInsideOrg: this._userModel.isInsideOrg(), hasWriteAccess: this._hasWriteAccess() }) ); this._initViews(); return this; }, _hasWriteAccess: function () { var permissionModel = this._tableModel._permissionModel; return permissionModel.isOwner(this._userModel) || permissionModel.hasWriteAccess(this._userModel); }, _initBinds: function () { this.listenTo(this._syncModel, 'change:state change:interval destroy', this.render); this.listenTo(this._visModel, 'change:name', this._onChangeName); this.listenTo(this._visModel, 'change:privacy change:name', this.render); this.listenTo(this._querySchemaModel, 'change:query', this.render); }, _initViews: function () { var isDatasetOwner = this._isDatasetOwner(); var toggleMenuTooltip = new TipsyTooltipView({ el: this.$('.js-toggle'), gravity: 'w', title: function () { return this._isHidden() ? _t('editor.layers.options.show') : _t('editor.layers.options.hide'); }.bind(this) }); this.addView(toggleMenuTooltip); if (isDatasetOwner) { if (this._tableModel.isSync()) { var syncTooltip = new TipsyTooltipView({ el: this.$('.js-syncState'), gravity: 'n', title: function () { return this._getSyncInfo(); }.bind(this) }); this.addView(syncTooltip); } else { this._inlineEditor = new InlineEditorView({ template: templateInlineEditor, renderOptions: { name: this._tableModel.getUnqualifiedName() }, onEdit: this._onRenameTable.bind(this) }); this.$('.js-name').html(this._inlineEditor.render().el); this.addView(this._inlineEditor); } if (this._userModel.isInsideOrg()) { var shareWith = new ShareWith({ visDefinitionModel: this._visModel, userModel: this._userModel, separationClass: 'u-rSpace--m', clickPrivacyAction: this._clickPrivacy.bind(this) }); this.$('.js-share-users').append(shareWith.render().el); this.addView(shareWith); } } var privacyDropdown = new PrivacyDropdown({ privacyCollection: this._privacyCollection, visDefinitionModel: this._visModel, userModel: this._userModel, configModel: this._configModel, isOwner: isDatasetOwner, ownerName: !isDatasetOwner && this._tableModel.getOwnerName() }); this.$('.js-dropdown').append(privacyDropdown.render().el); this.addView(privacyDropdown); }, _showContextMenu: function (ev) { var isSync = this._tableModel.isSync(); var triggerElementID = 'context-menu-trigger-' + this._tableModel.cid; this.$('.js-options').attr('id', triggerElementID); if (this._menuView && this._menuView.isVisible()) { this._menuView.hide(); this._menuView.clean(); delete this._menuView; return; } this._menuView = createContextMenu({ ev: ev, isTableOwner: this._isDatasetOwner(), isCustomQuery: this._isCustomQueryApplied(), isDOSubscription: this._isDOSubscription(), isSync: isSync, triggerElementID: triggerElementID, canCreateDatasets: this._userModel.canCreateDatasets() }); this._menuView.bind('rename', function () { this._inlineEditor && this._inlineEditor.edit(); }, this); this._menuView.bind('delete', this._deleteDataset, this); this._menuView.bind('duplicate', this._duplicateDataset, this); this._menuView.bind('lock', this._lockDataset, this); this._menuView.bind('metadata', this._metadataDataset, this); this._menuView.show(); this.addView(this._menuView); }, _deleteDataset: function () { var self = this; this._modals.create(function (modalModel) { return new RemoveDatasetModalView({ modalModel: modalModel, userModel: self._userModel, visModel: self._visModel, tableModel: self._tableModel, configModel: self._configModel }); }); }, _duplicateDataset: function () { var self = this; var tableName = this._tableModel.getUnquotedName(); var name = this._isCustomQueryApplied() ? _t('dataset.duplicate.query') : tableName; this._modals.create(function (modalModel) { return new CreationModalView({ modalModel: modalModel, loadingTitle: _t('dataset.duplicate.loading', { name: name }), errorTitle: _t('dataset.duplicate.error', { name: name }), runAction: function (opts) { tableDuplicationOperation({ query: self._querySchemaModel.get('query'), tableModel: self._tableModel, configModel: self._configModel, onSuccess: function (importModel) { var tableName = importModel.get('table_name'); var visTableModel = new VisTableModel({ id: tableName, table: { name: tableName } }, { configModel: self._configModel }); window.location = visTableModel.datasetURL(); }, onError: function (importModel) { var error = importModel.get('get_error_text'); var errorMessage = error && error.title; opts.error && opts.error(errorMessage); } }); } }); }, { escapeOptionsDisabled: true }); }, _lockDataset: function () { var self = this; var tableName = this._tableModel.getUnquotedName(); this._modals.create(function (modalModel) { return new CreationModalView({ modalModel: modalModel, loadingTitle: _t('dataset.lock.loading', { tableName: tableName }), errorTitle: _t('dataset.lock.error', { tableName: tableName }), runAction: function (opts) { self._visModel.save({ locked: true }, { wait: true, success: function () { window.location = self._configModel.get('base_url') + '/dashboard/datasets'; }, error: function () { opts.error && opts.error(); } }); } }); }); }, _metadataDataset: function () { var isLocked = this._tableModel.isSync(); var self = this; this._modals.create(function (modalModel) { return new EditMetadataView({ modalModel: modalModel, visDefinitionModel: self._visModel, configModel: self._configModel, isLocked: isLocked }); }); }, _onRenameTable: function (newName) { var self = this; this._inlineEditor.hide(); if (newName === this._visModel.get('name')) { return; } this._modals.create(function (modalModel) { return new ConfirmationModalView({ modalModel: modalModel, template: templateConfirmation, renderOpts: { tableName: self._visModel.get('name') }, runAction: function () { modalModel.destroy(); renameTableOperation({ visModel: self._visModel, newName: newName, onError: self._onRenameFailed.bind(self) }); } }); }); }, _onRenameFailed: function () { this._visModel.set('name', this._visModel.previous('name'), { silent: true }); this.render(); }, _onChangeName: function () { var name = this._visModel.get('name'); this._analysisDefinitionNodeModel.setTableName(name); this._setDocumentTitle(); this._layerDefinitionModel.save({ sql: this._analysisDefinitionNodeModel.getDefaultQuery() }); this._router.navigate(name, { replace: true }); }, _getSyncInfo: function () { var state = this._syncModel.get('state'); if (state === 'success') { return _t('dataset.sync.synced', { ranAt: moment(this._syncModel.get('ran_at') || new Date()).fromNow() }); } else if (state === 'failure') { var errorCode = this._syncModel.get('error_code'); var errorMessage = this._syncModel.get('error_message'); return _t('dataset.sync.error-code', { errorCode: errorCode }) + ':' + errorMessage; } else { return _t('dataset.sync.syncing'); } }, _clickPrivacy: function () { var self = this; this._modals.create(function (modalModel) { return new PublishView({ mapcapsCollection: self._mapcapsCollection, modalModel: modalModel, visDefinitionModel: self._visModel, privacyCollection: self._privacyCollection, userModel: self._userModel, configModel: self._configModel, mode: 'share', isOwner: self._isDatasetOwner() }); }); }, _setDocumentTitle: function () { document.title = this._tableModel.get('name') + TITLE_SUFFIX; }, _isCustomQueryApplied: function () { return this._analysisDefinitionNodeModel.isCustomQueryApplied(); }, _isEditable: function () { return !this._analysisDefinitionNodeModel.isReadOnly(); }, _isDatasetOwner: function () { return this._tableModel.isOwner(this._userModel); }, _isDOSubscription: function () { var subscription = this._visModel.get('subscription'); return subscription && subscription.provider === 'do-v2' || false; } });