cartodb/lib/assets/javascripts/builder/deep-insights-integration/analyses-integration.js
2020-06-15 10:58:47 +08:00

191 lines
6.2 KiB
JavaScript

var _ = require('underscore');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var AnalysisOnboardingLauncher = require('builder/components/onboardings/analysis/analysis-launcher');
var AnalysisNotifications = require('builder/editor/layers/analysis-views/analysis-notifications');
var REQUIRED_OPTS = [
'diDashboardHelpers',
'analysisDefinitionsCollection',
'analysisDefinitionNodesCollection',
'layerDefinitionsCollection',
'onboardings',
'userModel',
'visDefinitionModel'
];
/**
* Only manage **ANALYSIS NODES** and **ANALYSIS DEFINITION** actions between
* Deep-Insights (CARTO.js) and Builder
*
*/
module.exports = {
track: function (options) {
checkAndBuildOpts(options, REQUIRED_OPTS, this);
this._analysisDefinitionNodesCollection.each(function (analysisDefinitionNode) {
analysisDefinitionNode.queryRowsCollection.on('remove', this._invalidateMap, this);
}, this);
this._analysisDefinitionNodesCollection.on('add', this._onAnalysisDefinitionNodeAdded, this);
this._analysisDefinitionNodesCollection.on('change', this._onAnalysisDefinitionNodeChanged, this);
this._analysisDefinitionNodesCollection.on('change:id', this._onAnalysisDefinitionNodeIdChanged, this);
this._analysisDefinitionNodesCollection.on('remove', this._onAnalysisDefinitionNodeRemoved, this);
this._analysisDefinitionsCollection.on('add', this._onAnalysisDefinitionAdded, this);
this._analysisDefinitionsCollection.on('sync', this._onAnalysisDefinitionSync, this);
this._analysisDefinitionsCollection.each(this._analyseDefinition, this);
return this;
},
_onAnalysisDefinitionNodeAdded: function (node) {
node.queryRowsCollection.on('remove', this._invalidateMap, this);
this.analyseDefinitionNode(node);
},
_onAnalysisDefinitionNodeChanged: function (node) {
if (!this._hasUpdatedOnlyNodeAnalysisStatus(node)) {
// Only call analyse if there is a non-only-status change
this.analyseDefinitionNode(node);
}
},
_onAnalysisDefinitionNodeIdChanged: function (node) {
if (this._hasUpdatedOnlyNodeAnalysisId(node)) {
var analysis = this._diDashboardHelpers.getAnalysisByNodeId(node.previous('id'));
if (analysis) {
analysis.set('id', node.id);
}
}
},
_onAnalysisDefinitionNodeRemoved: function (node) {
node.queryRowsCollection.off('remove', this._invalidateMap, this);
var analysis = this._diDashboardHelpers.getAnalysisByNodeId(node.previous('id'));
if (analysis) {
analysis.set({avoidNotification: (node && !!node.get('avoidNotification'))}, {silent: true});
analysis.remove();
}
},
_onAnalysisDefinitionAdded: function (definition) {
this._analyseDefinition(definition);
},
_onAnalysisDefinitionSync: function (definition) {
this._analyseDefinition(definition);
},
_analyseDefinition: function (definition) {
var id = definition.get('node_id');
var node = this._analysisDefinitionNodesCollection.get(id);
this.analyseDefinitionNode(node);
},
analyseDefinitionNode: function (node) {
if (!this._hasUpdatedOnlyNodeAnalysisId(node)) {
var attrs = node.toJSON({ skipOptions: true });
this._diDashboardHelpers.analyse(attrs);
this._tryToSetupDefinitionNodesSync();
}
},
_hasUpdatedOnlyNodeAnalysisStatus: function (node) {
return node.hasChanged('status') && _.size(node.changed) === 1;
},
_hasUpdatedOnlyNodeAnalysisId: function (node) {
return node.hasChanged('id') && _.size(node.changed) === 1;
},
_tryToSetupDefinitionNodesSync: function () {
// Unfortunately have to try to setup sync until this point, since a node doesn't exist until after analyse call
this._analysisDefinitionNodesCollection.each(this._tryToSetupDefinitionNodeSync, this);
},
_tryToSetupDefinitionNodeSync: function (node) {
var isCachedAnalysis = this._isCachedAnalysis(node);
if (node.__syncSetup && !isCachedAnalysis) return; // only setup once
var analysis = this._diDashboardHelpers.getAnalysisByNodeId(node.id);
var layerDefinition = this._layerDefinitionsCollection.findOwnerOfAnalysisNode(node);
if (!analysis) return; // might not exist when method is called, so do nothing to allow retries
node.__syncSetup = true;
node.__initialization = true;
if (isCachedAnalysis) {
AnalysisOnboardingLauncher.launch(analysis.get('type'), node);
node.USER_SAVED = false;
return;
}
// Don't need to sync source nodes
if (analysis.get('type') !== 'source') {
AnalysisNotifications.track(analysis, layerDefinition);
var updateAnalysisQuerySchema = function () {
var query = analysis.get('query');
var status = analysis.get('status');
var error = analysis.get('error');
node.querySchemaModel.set({
status: 'unfetched',
query: query,
ready: status === 'ready'
});
node.queryGeometryModel.set({
status: 'unfetched',
query: query,
ready: status === 'ready'
});
node.set({
status: status,
error: error
});
if (status === 'ready') {
if (!node.__initialization) {
node.trigger('queryObjectsUpdated', node);
}
node.__initialization = false;
}
};
AnalysisOnboardingLauncher.init({
onboardings: this._onboardings,
userModel: this._userModel,
visDefinitionModel: this._visDefinitionModel
});
node.listenTo(analysis, 'change:status', function (model, status) {
if (status === 'ready' && node.USER_SAVED) {
AnalysisOnboardingLauncher.launch(analysis.get('type'), model);
node.USER_SAVED = false;
}
});
updateAnalysisQuerySchema();
node.listenTo(analysis, 'change:query change:status change:error', updateAnalysisQuerySchema);
node.listenToOnce(analysis, 'destroy', node.stopListening);
} else {
node.listenTo(node.querySchemaModel, 'resetDueToAlteredData', this._invalidateMap.bind(this));
}
},
_isCachedAnalysis: function (node) {
return node.hasChanged('status') && node.get('status') === 'ready' && node.previous('status') === 'launched';
},
_invalidateMap: function () {
this._diDashboardHelpers.invalidateMap();
}
};