cartodb-4.42/lib/assets/javascripts/cartodb/table/header/header_sync_info.js
2024-04-06 05:25:13 +00:00

222 lines
5.8 KiB
JavaScript

/**
* Header sync info when visualization is table type
*
* - If there is any change in the state, it will be rendered again.
*
* new cdb.admin.SyncInfo({
* model: synchronization_model
* });
*/
cdb.admin.SyncInfo = cdb.core.View.extend({
tagName: 'div',
className: 'sync_info',
_SYNC_GAP: 15, // Gap necessary to perform next synchronization
// Value in MINUTES
_POLLING_GAP: 15, // Gap necessary to start polling and checking
// synchronization. Value in SECONDS
_TEXTS: {
enabled: _t('This table will be synced again <%- run_at %>'),
few_moments: _t('in a few moments'),
sync_now_disabled: _t('You will be able to sync manually <%- gap %> minutes after your last synchronization')
},
events: {
'click a.sync_options': '_onClickOptions',
'click a.sync_now': '_onClickSyncNow'
},
initialize: function() {
_.bindAll(this, '_startSync');
this.dataLayer = this.options.dataLayer;
this.table = this.dataLayer.table;
this.model = this.table.synchronization;
this.template = cdb.templates.getTemplate('table/header/views/sync_info_content');
this.model.bind('change', this.render, this);
// Check sync now button
if (this._isSyncing()) {
this._showSyncNow();
this._startSync();
}
},
render: function() {
var attrs = _.clone(this.model.attributes);
var self = this;
// Destroy tipsy just in case
this._destroyTipsy();
attrs.ran_at = moment(attrs.ran_at || new Date()).fromNow();
// Due to the time we need to polling, we have to display to the user
// that the sync will be in a moment
if (!attrs.run_at || (new Date(attrs.run_at) <= new Date())) {
attrs.run_at = this._TEXTS.few_moments;
} else {
attrs.run_at = moment(attrs.run_at).fromNow();
}
// Can table be synced?
attrs.canSync = this._canTableSyncNow() ? true : false ;
// Come from external source?
attrs.fromExternalSource = this.model.get("from_external_source");
// Render
this.$el
.html(this.template(attrs))
.attr('class', '')
.addClass(attrs.state + ' ' + this.className);
// Tipsy?
this.$(".sync_now_disabled").tipsy({
gravity: 's',
fade: true,
title: function() {
return _.template(self._TEXTS.sync_now_disabled)({ gap: self._SYNC_GAP })
}
});
return this;
},
_bindEvents: function() {
this.model.bind('change:state', this._onStateChange, this);
},
_unbindEvents: function() {
this.model.unbind('change:state', this._onStateChange, this)
},
// Helpers
_canTableSyncNow: function() {
var ran_at = new Date(this.model.get('ran_at'));
var now = new Date();
var state = this.model.get('state');
var gap = this._SYNC_GAP*60*1000; // Importer needs some time to perform the next sync,
// set 15 min as default.
// If table is syncing... false!
if (state === "syncing") {
return false
}
if (( now.getTime() - ran_at.getTime() ) > gap) {
return true;
} else {
return false;
}
},
_isSyncing: function() {
return this.model.get('state') === "syncing";
},
// UI bind events //
_onClickSyncNow: function(e) {
if (e) this.killEvent(e);
if (this._canTableSyncNow()) {
// Set syncing state
this.model.set('state', 'syncing');
// Show dialog
this._showSyncNow();
// Enqueue synchronization
this.model.syncNow(this._startSync);
}
},
_onClickOptions: function(e) {
if (e) this.killEvent(e);
var dialog = new cdb.editor.SyncView({
clean_on_hide: true,
enter_to_confirm: true,
table: this.table
});
dialog.appendToBody();
},
_startSync: function() {
// Render again
this.render();
// Bind events
this._bindEvents();
// We MUST wait before start polling
var self = this;
_.delay(function() {
self.model.pollCheck();
}, (this._POLLING_GAP * 1000)); // polling gap * miliseconds
},
_finishSync: function() {
this._unbindEvents();
this.model.destroyCheck();
this._hideSyncNow();
// Reload table and map data
this.dataLayer.invalidate();
this.table.data().refresh();
},
_onStateChange: function() {
this._finishSync();
// Success state could be wrong if any error_code
// or error_message appears in the model
if (this.model.get('state') === "success" &&
(this.model.get('error_code') || this.model.get('error_message'))
) {
this.model.set('state', 'failure');
}
this.render();
},
// Show or hide sync now modal //
_showSyncNow: function(e) {
if (e) this.killEvent(e);
var modal = cdb.editor.ViewFactory.createDialogByTemplate('common/templates/loading', {
title: 'Your dataset is being synced…',
quote: "This action will take some time. In the meantime the UI is disabled, but APIs will work as usual."
}, { sticky: true }).render();
this.sync_now = modal;
modal.appendToBody();
},
_hideSyncNow: function() {
if (this.sync_now) {
this.sync_now.hide();
}
},
_destroyTipsy: function() {
// Remove tipsy
if (this.$('.sync_now_disabled').data('tipsy')) {
this.$('.sync_now_disabled')
.unbind('mouseenter mouseleave')
.data('tipsy').remove();
}
},
clean: function() {
this._destroyTipsy();
cdb.core.View.prototype.clean.call(this);
}
})