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

193 lines
6.8 KiB
JavaScript

var _ = require('underscore');
var WidgetModel = require('./widgets/widget-model');
var CategoryWidgetModel = require('./widgets/category/category-widget-model');
var HistogramWidgetModel = require('./widgets/histogram/histogram-widget-model');
var TimeSeriesWidgetModel = require('./widgets/time-series/time-series-widget-model');
var WIDGETSTYLEPARAMS = {
auto_style_allowed: 'autoStyleEnabled'
};
// We create an object with options off the attributes
var makeWidgetStyleOptions = function (attrs) {
return _.reduce(WIDGETSTYLEPARAMS, function (memo, value, key) {
if (attrs[key] !== undefined) {
memo[value] = attrs[key];
return memo;
}
}, {});
};
var _checkProperties = function (obj, propertiesArray) {
_.each(propertiesArray, function (prop) {
if (obj[prop] === undefined) {
throw new Error(prop + ' is required');
}
});
};
var extendAttrs = function (attrs, state, hasInitialState) {
return _.extend(attrs, state, { hasInitialState: hasInitialState }); // Will overwrite preset attributes with the ones passed on the state
};
var checkAnalysisModel = function (attrs) {
if (!(attrs.source instanceof Object) || !attrs.source.cid) {
throw new Error('Source must be defined and be an instance of AnalysisModel.');
}
};
/**
* Public API to interact with dashboard widgets.
*/
var WidgetsService = function (widgetsCollection, dataviews) {
this._widgetsCollection = widgetsCollection;
this._dataviews = dataviews;
};
WidgetsService.prototype.getCollection = function () {
return this._widgetsCollection;
};
WidgetsService.prototype.get = function (id) {
return this._widgetsCollection.get(id);
};
WidgetsService.prototype.getList = function () {
return this._widgetsCollection.models;
};
/**
* @param {Object} attrs
* @param {String} attrs.title Title rendered on the widget view
* @param {String} attrs.column Name of column to use to aggregate
* @param {String} attrs.aggregation Name of aggregation operation to apply to get categories
* can be any of ['sum', 'count']. Default is 'count'
* @param {String} attrs.aggregation_column column to be used for the aggregation operation
* it only applies for sum operations.
* @param {Object} attrs.source Object with the id of the source analysis node that the widget points to
* @param {Object} layer Instance of a layer model (cartodb.js)
* @return {CategoryWidgetModel}
*/
WidgetsService.prototype.createCategoryModel = function (attrs, layer, state) {
_checkProperties(attrs, ['title']);
var extendedAttrs = extendAttrs(attrs, state, this._widgetsCollection.hasInitialState());
checkAnalysisModel(extendedAttrs);
var dataviewModel = this._dataviews.createCategoryModel(extendedAttrs);
var ATTRS_NAMES = ['id', 'title', 'order', 'collapsed', 'prefix', 'suffix', 'show_stats', 'show_source', 'style', 'hasInitialState'];
var widgetAttrs = _.pick(extendedAttrs, ATTRS_NAMES);
var options = makeWidgetStyleOptions(extendedAttrs);
widgetAttrs.attrsNames = ATTRS_NAMES;
var widgetModel = new CategoryWidgetModel(widgetAttrs, {
dataviewModel: dataviewModel,
layerModel: layer
}, options);
widgetModel.setInitialState(state);
this._widgetsCollection.add(widgetModel);
return widgetModel;
};
/**
* @param {Object} attrs
* @param {String} attrs.title Title rendered on the widget view
* @param {String} attrs.column Name of column
* @param {Number} attrs.bins Count of bins
* @param {Object} layer Instance of a layer model (cartodb.js)
* @return {WidgetModel}
*/
WidgetsService.prototype.createHistogramModel = function (attrs, layer, state, opts) {
_checkProperties(attrs, ['title']);
var extendedAttrs = extendAttrs(attrs, state, this._widgetsCollection.hasInitialState());
checkAnalysisModel(extendedAttrs);
var dataviewModel = this._dataviews.createHistogramModel(extendedAttrs);
// Default bins attribute was removed from dataViewModel because of time-series aggregation.
// Just in case it's needed for histogram models we added it here.
if (!dataviewModel.has('bins')) {
dataviewModel.set('bins', 10, { silent: true });
}
var attrsNames = ['id', 'title', 'order', 'collapsed', 'bins', 'show_stats', 'show_source', 'normalized', 'style', 'hasInitialState', 'table_name'];
var widgetAttrs = _.pick(extendedAttrs, attrsNames);
var options = makeWidgetStyleOptions(extendedAttrs);
widgetAttrs.type = 'histogram';
widgetAttrs.attrsNames = attrsNames;
var widgetModel = new HistogramWidgetModel(widgetAttrs, {
dataviewModel: dataviewModel,
layerModel: layer
}, options);
widgetModel.setInitialState(state);
this._widgetsCollection.add(widgetModel);
return widgetModel;
};
/**
* @param {Object} attrs
* @param {String} attrs.title Title rendered on the widget view
* @param {String} attrs.column Name of column
* @param {String} attrs.operation Name of operation to use, can be any of ['min', 'max', 'avg', 'sum']
* @param {Object} layer Instance of a layer model (cartodb.js)
* @return {CategoryWidgetModel}
*/
WidgetsService.prototype.createFormulaModel = function (attrs, layer, state) {
_checkProperties(attrs, ['title']);
var extendedAttrs = extendAttrs(attrs, state, this._widgetsCollection.hasInitialState());
checkAnalysisModel(extendedAttrs);
var dataviewModel = this._dataviews.createFormulaModel(extendedAttrs);
var ATTRS_NAMES = ['id', 'title', 'order', 'collapsed', 'prefix', 'suffix', 'show_stats', 'show_source', 'description', 'hasInitialState'];
var widgetAttrs = _.pick(extendedAttrs, ATTRS_NAMES);
widgetAttrs.type = 'formula';
widgetAttrs.attrsNames = ATTRS_NAMES;
var widgetModel = new WidgetModel(widgetAttrs, {
dataviewModel: dataviewModel,
layerModel: layer
});
widgetModel.setInitialState(state);
this._widgetsCollection.add(widgetModel);
return widgetModel;
};
/**
* @param {Object} attrs
* @param {String} attrs.column Name of column that contains
* @param {Object} layer Instance of a layer model (cartodb.js)
* @param {Number} bins
* @return {WidgetModel}
*/
WidgetsService.prototype.createTimeSeriesModel = function (attrs, layer, state, opts) {
// TODO will other kind really work for a time-series?
attrs.column_type = attrs.column_type || 'date';
checkAnalysisModel(attrs);
var dataviewModel = this._dataviews.createHistogramModel(attrs);
var ATTRS_NAMES = ['id', 'style', 'title', 'normalized', 'animated', 'timezone'];
var widgetAttrs = _.pick(attrs, ATTRS_NAMES);
widgetAttrs.type = 'time-series';
widgetAttrs.attrsNames = ATTRS_NAMES;
var widgetModel = new TimeSeriesWidgetModel(widgetAttrs, {
dataviewModel: dataviewModel,
layerModel: layer
}, opts);
widgetModel.setInitialState(state);
this._widgetsCollection.add(widgetModel);
return widgetModel;
};
WidgetsService.prototype.setWidgetsState = function (state) {
this._widgetsCollection.setStates(state);
};
module.exports = WidgetsService;