Initial commit
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
var $ = require('jquery');
|
||||
var cdb = require('internal-carto.js');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view.js');
|
||||
var NotificationErrorMessageHandler = require('builder/editor/layers/notification-error-message-handler');
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
initialize: function (opts) {
|
||||
if (!opts.analysisNode) throw new Error('analysisNode is required');
|
||||
if (!opts.element) throw new Error('element is required');
|
||||
if (!opts.triggerSelector) throw new Error('triggerSelector is required');
|
||||
|
||||
this.analysisNode = opts.analysisNode;
|
||||
this.$el = opts.element;
|
||||
this.selector = opts.triggerSelector;
|
||||
|
||||
this.$el.on('mouseover', this.selector, this._showTooltip.bind(this));
|
||||
this.$el.on('mouseout', this.selector, this._destroyTooltip.bind(this));
|
||||
this.$el.on('mouseleave', this.selector, this._destroyTooltip.bind(this));
|
||||
},
|
||||
|
||||
_showTooltip: function (e) {
|
||||
var status = this.analysisNode.get('status');
|
||||
|
||||
if (status === 'failed') {
|
||||
var message = NotificationErrorMessageHandler.extractErrorFromAnalysisNode(this.analysisNode);
|
||||
|
||||
this.tooltip = this._createTooltip({
|
||||
$el: $(e.target),
|
||||
msg: message.message
|
||||
});
|
||||
|
||||
this.tooltip.showTipsy();
|
||||
}
|
||||
},
|
||||
|
||||
_createTooltip: function (opts) {
|
||||
return new TipsyTooltipView({
|
||||
el: opts.$el,
|
||||
title: function () {
|
||||
return opts.msg;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_destroyTooltip: function () {
|
||||
if (this.tooltip) {
|
||||
this.tooltip.hideTipsy();
|
||||
this.tooltip.destroyTipsy();
|
||||
delete this.tooltip;
|
||||
}
|
||||
},
|
||||
|
||||
clean: function () {
|
||||
this.$el.off('mouseover', this.selector);
|
||||
this.$el.off('mouseout', this.selector);
|
||||
this.$el.off('mouseleave', this.selector);
|
||||
|
||||
this._destroyTooltip();
|
||||
cdb.core.View.prototype.clean.call(this);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,130 @@
|
||||
var _ = require('underscore');
|
||||
var Notifier = require('builder/components/notifier/notifier');
|
||||
var NotificationErrorMessageHandler = require('builder/editor/layers/notification-error-message-handler');
|
||||
|
||||
var DEFAULT_DELAY = Notifier.DEFAULT_DELAY;
|
||||
var STATUS_READY = 'ready';
|
||||
var STATUS_PENDING = 'pending';
|
||||
var STATUS_RUNNING = 'running';
|
||||
var STATUS_WAITING = 'waiting';
|
||||
var STATUS_FAILED = 'failed';
|
||||
|
||||
var AnalysisNotifications = {
|
||||
|
||||
track: function (analysisNode, layerDefModel) {
|
||||
analysisNode.on('change:status', this._addStatusChangedNotification, this);
|
||||
analysisNode.on('change:error', this._onErrorChanged, this);
|
||||
analysisNode.once('destroy', this._addRemovedNotification, this);
|
||||
this._layerDefModel = layerDefModel;
|
||||
|
||||
if (analysisNode.get('status') && analysisNode.get('status') !== STATUS_READY) {
|
||||
this._addStatusChangedNotification(analysisNode);
|
||||
}
|
||||
},
|
||||
|
||||
_addRemovedNotification: function (analysisNode) {
|
||||
if (analysisNode.get('avoidNotification') === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
var nodeId = analysisNode.get('id');
|
||||
var notificationAttrs = {
|
||||
status: 'success',
|
||||
info: _t('notifications.analysis.removed', {
|
||||
nodeId: nodeId.toUpperCase()
|
||||
}),
|
||||
closable: true,
|
||||
delay: DEFAULT_DELAY
|
||||
};
|
||||
this._addOrUpdateNotification(analysisNode.cid, notificationAttrs);
|
||||
},
|
||||
|
||||
_addStatusChangedNotification: function (analysisNode) {
|
||||
var status = analysisNode.get('status');
|
||||
if (status === STATUS_WAITING || status === STATUS_PENDING) {
|
||||
this._addAnalysisWaitingNotification(analysisNode);
|
||||
}
|
||||
if (status === STATUS_RUNNING) {
|
||||
this._addAnalysisRunningNotification(analysisNode);
|
||||
}
|
||||
if (status === STATUS_READY) {
|
||||
this._addAnalysisReadyNotification(analysisNode);
|
||||
}
|
||||
if (status === STATUS_FAILED) {
|
||||
this._addAnalysisFailedNotification(analysisNode);
|
||||
}
|
||||
},
|
||||
|
||||
_addAnalysisWaitingNotification: function (analysisNode) {
|
||||
var notificationAttrs = {
|
||||
status: 'loading',
|
||||
info: _t('notifications.analysis.waiting', {
|
||||
nodeId: analysisNode.get('id').toUpperCase()
|
||||
})
|
||||
};
|
||||
this._addOrUpdateNotification(analysisNode.cid, notificationAttrs);
|
||||
},
|
||||
|
||||
_addAnalysisRunningNotification: function (analysisNode) {
|
||||
var notificationAttrs = {
|
||||
status: 'loading',
|
||||
info: _t('notifications.analysis.running', {
|
||||
nodeId: analysisNode.get('id').toUpperCase()
|
||||
})
|
||||
};
|
||||
this._addOrUpdateNotification(analysisNode.cid, notificationAttrs);
|
||||
},
|
||||
|
||||
_addAnalysisReadyNotification: function (analysisNode) {
|
||||
var notificationAttrs = {
|
||||
status: 'success',
|
||||
info: _t('notifications.analysis.completed', {
|
||||
nodeId: analysisNode.get('id').toUpperCase()
|
||||
}),
|
||||
closable: true,
|
||||
delay: DEFAULT_DELAY
|
||||
};
|
||||
this._addOrUpdateNotification(analysisNode.cid, notificationAttrs);
|
||||
},
|
||||
|
||||
_addAnalysisFailedNotification: function (analysisNode) {
|
||||
var message = NotificationErrorMessageHandler.extractErrorFromAnalysisNode(analysisNode, this._layerDefModel);
|
||||
|
||||
var notificationAttrs = {
|
||||
status: message.type,
|
||||
info: message.message,
|
||||
closable: true,
|
||||
autoclosable: false
|
||||
};
|
||||
|
||||
this._addOrUpdateNotification(analysisNode.cid, notificationAttrs);
|
||||
},
|
||||
|
||||
_addOrUpdateNotification: function (notificationId, notificationAttrs) {
|
||||
var notification = this._getNotification(notificationId);
|
||||
if (notification) {
|
||||
notification.set(notificationAttrs);
|
||||
} else {
|
||||
this._addNotification(notificationId, notificationAttrs);
|
||||
}
|
||||
},
|
||||
|
||||
_addNotification: function (notificationId, notificationAttrs) {
|
||||
notificationAttrs = _.extend({
|
||||
id: notificationId
|
||||
}, notificationAttrs);
|
||||
Notifier.addNotification(notificationAttrs);
|
||||
},
|
||||
|
||||
_getNotification: function (notificationId) {
|
||||
return Notifier.getNotification(notificationId);
|
||||
},
|
||||
|
||||
_onErrorChanged: function (analysisNode, error) {
|
||||
if (error) {
|
||||
this._addAnalysisFailedNotification(analysisNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AnalysisNotifications;
|
||||
@@ -0,0 +1,82 @@
|
||||
var CoreView = require('backbone/core-view');
|
||||
var SourceLayerAnalysisView = require('./source-layer-analysis-view');
|
||||
var DefaultLayerAnalysisView = require('./default-layer-analysis-view');
|
||||
var template = require('./composite-layer-analysis-view.tpl');
|
||||
|
||||
/**
|
||||
* View for an analysis node which have two source nodes as input.
|
||||
* The primary source node is rendered separately, this view renders the own node + the secondary one.
|
||||
* _____________ ___________________
|
||||
* | own node | ------ | secondary node |
|
||||
* |____________| |__________________|
|
||||
* |
|
||||
* ________________
|
||||
* | primary node |
|
||||
* |________________|
|
||||
*
|
||||
* this.model is expected to be a analysis-definition-node-nodel
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
tagName: 'li',
|
||||
className: 'Editor-ListAnalysis-item',
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.analysisDefinitionNodesCollection) throw new Error('analysisDefinitionNodesCollection is required');
|
||||
if (!opts.layerDefinitionModel) throw new Error('layerDefinitionModel is required');
|
||||
|
||||
this._analysisDefinitionNodesCollection = opts.analysisDefinitionNodesCollection;
|
||||
this._layerDefinitionModel = opts.layerDefinitionModel;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
this.$el.html(template());
|
||||
|
||||
this._renderOwnNode();
|
||||
this._renderSecondaryNode();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderOwnNode: function () {
|
||||
var view = new DefaultLayerAnalysisView({
|
||||
tagName: 'div',
|
||||
model: this.model,
|
||||
analysisNode: this._analysisDefinitionNodesCollection.get(this.model.id),
|
||||
layerDefinitionModel: this._layerDefinitionModel
|
||||
});
|
||||
this.addView(view);
|
||||
this.$('.js-primary-source').append(view.render().el);
|
||||
},
|
||||
|
||||
_renderSecondaryNode: function () {
|
||||
var nodeDefModel = this.model.getSecondarySource();
|
||||
var layerDefModel = this._layerDefinitionModel.collection.findOwnerOfAnalysisNode(nodeDefModel);
|
||||
|
||||
if (nodeDefModel) {
|
||||
var view = nodeDefModel.get('type') === 'source'
|
||||
? new SourceLayerAnalysisView({
|
||||
model: nodeDefModel,
|
||||
analysisNode: this._analysisDefinitionNodesCollection.get(nodeDefModel.id),
|
||||
layerDefinitionModel: this._layerDefinitionModel,
|
||||
showId: !!(layerDefModel && this._isOwnedByOtherLayer(layerDefModel))
|
||||
})
|
||||
: new DefaultLayerAnalysisView({
|
||||
tagName: 'div',
|
||||
model: nodeDefModel,
|
||||
analysisNode: this._analysisDefinitionNodesCollection.get(nodeDefModel.id),
|
||||
layerDefinitionModel: layerDefModel
|
||||
});
|
||||
|
||||
this.addView(view);
|
||||
this.$('.js-secondary-source').append(view.render().el);
|
||||
}
|
||||
},
|
||||
|
||||
_isOwnedByOtherLayer: function (layerDefModel) {
|
||||
return layerDefModel !== this._layerDefinitionModel;
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
<ul class="Editor-ListAnalysis-inner">
|
||||
<li class="Editor-ListAnalysis-innerItem js-primary-source"></li>
|
||||
<li class="Editor-ListAnalysis-innerItem js-secondary-source"></li>
|
||||
</ul>
|
||||
@@ -0,0 +1,102 @@
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var nodeIds = require('builder/value-objects/analysis-node-ids');
|
||||
var layerColors = require('builder/data/layer-colors');
|
||||
var template = require('./default-layer-analysis-view.tpl');
|
||||
var Analyses = require('builder/data/analyses');
|
||||
var AnalysisTooltip = require('./analyses-tooltip-error');
|
||||
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view');
|
||||
|
||||
/**
|
||||
* View for an analysis node with a single input
|
||||
*
|
||||
* this.model is expected to be a analysis-definition-node-nodel
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
tagName: 'li',
|
||||
className: 'Editor-ListAnalysis-item Editor-ListAnalysis-layer CDB-Text is-semibold CDB-Size-small js-analysis-node',
|
||||
|
||||
events: {
|
||||
'mouseenter': '_onMouseEnter',
|
||||
'mouseleave': '_onMouseLeave'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.analysisNode) throw new Error('analysisNode is required');
|
||||
|
||||
this._analysisNode = opts.analysisNode;
|
||||
this._analysisNode.on('change:status', this.render, this);
|
||||
this.add_related_model(this._analysisNode);
|
||||
|
||||
this._analysisTooltip = new AnalysisTooltip({
|
||||
analysisNode: this._analysisNode,
|
||||
element: this.$el,
|
||||
triggerSelector: '.Editor-ListAnalysis-itemError'
|
||||
});
|
||||
this.addView(this._analysisTooltip);
|
||||
|
||||
this._stateModel = new Backbone.Model({
|
||||
highlighted: false
|
||||
});
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this._stateModel.on('change:highlighted', this._toggleHover, this);
|
||||
this.add_related_model(this._stateModel);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var status = this._analysisNode.get('status');
|
||||
|
||||
this.$el.html(template({
|
||||
id: this.model.id,
|
||||
bgColor: this._bgColor(),
|
||||
isDone: status === 'ready' || status === 'failed',
|
||||
title: Analyses.title(this.model),
|
||||
hasError: status === 'failed'
|
||||
}));
|
||||
this.$el.toggleClass('has-error', status === 'failed');
|
||||
|
||||
this.el.dataset.analysisNodeId = this.model.id;
|
||||
|
||||
this._initViews();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
var sourceTooltip = new TipsyTooltipView({
|
||||
el: this.$el,
|
||||
gravity: 'w',
|
||||
title: function () {
|
||||
return _t('edit-analysis');
|
||||
}
|
||||
});
|
||||
this.addView(sourceTooltip);
|
||||
},
|
||||
|
||||
_bgColor: function () {
|
||||
var letter = nodeIds.letter(this._analysisNode.id);
|
||||
return layerColors.getColorForLetter(letter);
|
||||
},
|
||||
|
||||
_onMouseEnter: function () {
|
||||
this._stateModel.set('highlighted', true);
|
||||
},
|
||||
|
||||
_onMouseLeave: function () {
|
||||
this._stateModel.set('highlighted', false);
|
||||
},
|
||||
|
||||
_toggleHover: function () {
|
||||
var $layer = this.$el.closest('.js-layer');
|
||||
var $title = $layer.find('.js-Editor-ListLayer-titleText');
|
||||
var highlighted = this._stateModel.get('highlighted');
|
||||
|
||||
$layer.toggleClass('is-hover', highlighted);
|
||||
$title.toggleClass('is-hover', highlighted);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
<div class="Editor-ListAnalysis-itemInfo u-rSpace--m CDB-Text is-semibold CDB-Size-small u-upperCase" style="background: <%- bgColor %>; color: #fff">
|
||||
<% if (isDone) { %>
|
||||
<span class="CDB-Text u-rSpace">
|
||||
<%- id %>
|
||||
</span>
|
||||
<i class="CDB-IconFont CDB-IconFont-ray CDB-Size-medium"></i>
|
||||
<% } else { %>
|
||||
<div class="CDB-LoaderIcon">
|
||||
<svg class="CDB-LoaderIcon-spinner" viewBox="0 0 50 50">
|
||||
<circle class="CDB-LoaderIcon-path" cx="25" cy="25" r="20" fill="none"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<p class="Editor-ListAnalysis-title CDB-Text CDB-Size-small u-secondaryTextColor u-ellipsis" title="<%- title %>"><%- title %></p>
|
||||
|
||||
<% if (hasError) { %>
|
||||
<div class="Editor-ListAnalysis-itemError"></div>
|
||||
<% } %>
|
||||
@@ -0,0 +1,79 @@
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var analyses = require('builder/data/analyses');
|
||||
var template = require('./ref-layer-analysis-view.tpl');
|
||||
|
||||
/**
|
||||
* View for an analysis node that belongs to another layer
|
||||
*
|
||||
* this.model is expected to be a analysis-definition-node-nodel
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
tagName: 'li',
|
||||
className: 'Editor-ListAnalysis-item Editor-ListAnalysis-layer CDB-Text is-semibold CDB-Size-small js-analysis-node',
|
||||
|
||||
events: {
|
||||
'mouseenter': '_onMouseEnter',
|
||||
'mouseleave': '_onMouseLeave'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.layerDefinitionModel) throw new Error('layerDefinitionModel is required');
|
||||
if (!opts.analysisNode) throw new Error('analysisNode is required');
|
||||
|
||||
this._layerDefinitionModel = opts.layerDefinitionModel;
|
||||
this._analysisNode = opts.analysisNode;
|
||||
|
||||
this._stateModel = new Backbone.Model({
|
||||
highlighted: false
|
||||
});
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._analysisNode, 'change:status', this.render);
|
||||
this.add_related_model(this._analysisNode);
|
||||
|
||||
this.listenTo(this._layerDefinitionModel, 'change', this.render);
|
||||
this.add_related_model(this._layerDefinitionModel);
|
||||
|
||||
this.listenTo(this._stateModel, 'change:highlighted', this._toggleHover);
|
||||
this.add_related_model(this._stateModel);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var status = this._analysisNode.get('status');
|
||||
|
||||
this.$el.html(template({
|
||||
id: this.model.id,
|
||||
layerName: this._layerDefinitionModel.getName(),
|
||||
bgColor: this.model.getColor(),
|
||||
isDone: status === 'ready' || status === 'failed',
|
||||
title: analyses.title(this.model)
|
||||
}));
|
||||
this.$el.toggleClass('has-error', status === 'failed');
|
||||
|
||||
this.el.dataset.analysisNodeId = this.model.id;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_onMouseEnter: function () {
|
||||
this._stateModel.set('highlighted', true);
|
||||
},
|
||||
|
||||
_onMouseLeave: function () {
|
||||
this._stateModel.set('highlighted', false);
|
||||
},
|
||||
|
||||
_toggleHover: function () {
|
||||
var $layer = this.$el.closest('.js-layer');
|
||||
var $title = $layer.find('.js-Editor-ListLayer-titleText');
|
||||
var highlighted = this._stateModel.get('highlighted');
|
||||
|
||||
$layer.toggleClass('is-hover', highlighted);
|
||||
$title.toggleClass('is-hover', highlighted);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
<div class="Editor-ListAnalysis-itemInfo u-rSpace--m CDB-Text is-semibold CDB-Size-small u-upperCase" style="background: <%- bgColor %>; color: #fff">
|
||||
<% if (isDone) { %>
|
||||
<span class="CDB-Text u-rSpace">
|
||||
<%- id %>
|
||||
</span>
|
||||
<i class="CDB-IconFont CDB-IconFont-ray CDB-Size-medium"></i>
|
||||
<% } else { %>
|
||||
<div class="CDB-LoaderIcon">
|
||||
<svg class="CDB-LoaderIcon-spinner" viewBox="0 0 50 50">
|
||||
<circle class="CDB-LoaderIcon-path" cx="25" cy="25" r="20" fill="none"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<p class="Editor-ListAnalysis-title CDB-Text CDB-Size-small u-secondaryTextColor u-ellipsis u-flex" title="<%- title %>">
|
||||
<%- title %> <span class="u-altTextColor u-lSpace u-ellipsis"><%- layerName %></span>
|
||||
</p>
|
||||
@@ -0,0 +1,137 @@
|
||||
var $ = require('jquery');
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var CoreView = require('backbone/core-view');
|
||||
var template = require('./source-layer-analysis-view.tpl');
|
||||
var TipsyTooltipView = require('builder/components/tipsy-tooltip-view');
|
||||
var moment = require('moment');
|
||||
|
||||
/**
|
||||
* View for a analysis source (i.e. SQL query).
|
||||
*
|
||||
* this.model is expected to be a analysis-definition-node-model and belong to the given layer-definition-model
|
||||
*/
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
tagName: 'li',
|
||||
className: 'Editor-ListAnalysis-item Editor-ListAnalysis-layer js-base is-base u-flex u-justifySpace',
|
||||
|
||||
events: {
|
||||
'mouseenter': '_onMouseEnter',
|
||||
'mouseleave': '_onMouseLeave'
|
||||
},
|
||||
|
||||
initialize: function (opts) {
|
||||
if (!opts.layerDefinitionModel) throw new Error('layerDefinitionModel is required');
|
||||
if (!opts.analysisNode) throw new Error('analysisNode is required');
|
||||
|
||||
this._layerDefinitionModel = opts.layerDefinitionModel;
|
||||
this._analysisNode = opts.analysisNode;
|
||||
this._tableNodeModel = this._analysisNode.getTableModel();
|
||||
this._stateModel = new Backbone.Model({
|
||||
highlighted: false
|
||||
});
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
options: {
|
||||
showId: true
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
var isSync = this._tableNodeModel && this._tableNodeModel.isSync();
|
||||
var syncData = {};
|
||||
|
||||
if (isSync) {
|
||||
var syncModel = this._tableNodeModel.getSyncModel();
|
||||
var runAt = syncModel.get('run_at');
|
||||
|
||||
syncData = {
|
||||
ranAt: moment(syncModel.get('ran_at') || new Date()).fromNow(),
|
||||
runAt: moment(runAt).fromNow(),
|
||||
state: syncModel.get('state'),
|
||||
errorCode: syncModel.get('error_code'),
|
||||
errorMessage: syncModel.get('error_message')
|
||||
};
|
||||
|
||||
// Due to the time we need to polling, we have to display to the user
|
||||
// that the sync will be in a moment
|
||||
if (!runAt || (new Date(runAt) <= new Date())) {
|
||||
syncData.runAt = _t('dataset.sync.in-a-moment');
|
||||
}
|
||||
}
|
||||
|
||||
var isCustomQueryApplied = this._analysisNode.isCustomQueryApplied();
|
||||
this.$el.html(template(_.extend({
|
||||
id: this.options.showId ? this.model.id : '',
|
||||
tableName: this.model.get('table_name'),
|
||||
customQueryApplied: isCustomQueryApplied,
|
||||
isSync: isSync,
|
||||
bgColor: this._analysisNode.getColor()
|
||||
}, syncData)));
|
||||
|
||||
var sourceTooltip = new TipsyTooltipView({
|
||||
el: this.$el,
|
||||
gravity: 'w',
|
||||
title: function () {
|
||||
return _t('data-source');
|
||||
}
|
||||
});
|
||||
this.addView(sourceTooltip);
|
||||
|
||||
if (isSync) {
|
||||
var syncTooltipTitle = (syncData.errorCode || syncData.errorMessage) ? _t('dataset.sync.error-code', { errorCode: syncData.errorCode }) + ':' + syncData.errorMessage : $(this).data('tooltip');
|
||||
var syncTooltip = new TipsyTooltipView({
|
||||
el: this.$('.js-sync'),
|
||||
gravity: 's',
|
||||
offset: 0,
|
||||
title: syncTooltipTitle
|
||||
});
|
||||
this.addView(syncTooltip);
|
||||
}
|
||||
|
||||
if (isCustomQueryApplied) {
|
||||
var sqlTooltip = new TipsyTooltipView({
|
||||
el: this.$('.js-sql'),
|
||||
gravity: 'w',
|
||||
title: function () {
|
||||
return _t('sql-applied');
|
||||
},
|
||||
mouseEnterAction: function () {
|
||||
sourceTooltip.hideTipsy();
|
||||
},
|
||||
mouseLeaveAction: function () {
|
||||
sourceTooltip.showTipsy();
|
||||
}
|
||||
});
|
||||
this.addView(sqlTooltip);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this._stateModel, 'change:highlighted', this._toggleHover);
|
||||
this.listenTo(this._tableNodeModel, 'change:synchronization', this.render);
|
||||
},
|
||||
|
||||
_onMouseEnter: function () {
|
||||
this._stateModel.set('highlighted', true);
|
||||
},
|
||||
|
||||
_onMouseLeave: function () {
|
||||
this._stateModel.set('highlighted', false);
|
||||
},
|
||||
|
||||
_toggleHover: function () {
|
||||
var $layer = this.$el.closest('.js-layer');
|
||||
var $title = $layer.find('.js-Editor-ListLayer-titleText');
|
||||
var highlighted = this._stateModel.get('highlighted');
|
||||
|
||||
$layer.toggleClass('is-hover', highlighted);
|
||||
$title.toggleClass('is-hover', highlighted);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
<p class="Editor-ListAnalysis-itemInfoTitle CDB-Text CDB-Size-small u-ellipsis u-flex" title="<%- tableName %>">
|
||||
<span class="CDB-Text is-semibold CDB-Size-small u-rSpace u-upperCase" style="color: <%- bgColor %>">
|
||||
<%- id %>
|
||||
</span>
|
||||
Source
|
||||
<span class="Editor-ListAnalysis-title u-altTextColor u-lSpace u-ellipsis">
|
||||
<%- tableName %>
|
||||
</span>
|
||||
</p>
|
||||
<% if (isSync) { %>
|
||||
<span class="Editor-ListAnalysis-itemInfoIcon">
|
||||
<div class="u-flex u-alignCenter CDB-Text CDB-Size-small u-altTextColor SyncInfo-message--<%- state %> js-sync" data-tooltip="<% if (errorCode || errorMessage) { %><%- _t('dataset.sync.sync-failed') %><% } else { %><%- ranAt %><% } %>">
|
||||
<i class="CDB-IconFont CDB-IconFont-wifi"></i>
|
||||
</div>
|
||||
</span>
|
||||
<% } %>
|
||||
<% if (customQueryApplied) { %>
|
||||
<span class="Editor-ListAnalysis-itemInfoIcon Tag Tag--outline Tag-outline--dark CDB-Text CDB-Size-small js-sql">
|
||||
SQL
|
||||
</span>
|
||||
<% } %>
|
||||
Reference in New Issue
Block a user