cartodb/lib/assets/javascripts/builder/data/widget-definitions-collection.js
2020-06-15 10:58:47 +08:00

221 lines
6.3 KiB
JavaScript
Executable File

var _ = require('underscore');
var Backbone = require('backbone');
var WidgetDefinitionModel = require('./widget-definition-model');
var checkAndBuildOpts = require('builder/helpers/required-opts');
var REQUIRED_OPTS = [
'configModel',
'mapId',
'layerDefinitionsCollection',
'analysisDefinitionNodesCollection'
];
/**
* Collection of widget definitions, synhronizes the internal definitions and the widget models.
*/
module.exports = Backbone.Collection.extend({
comparator: 'order',
model: function (attrs, opts) {
var self = opts.collection;
attrs.order = !_.isUndefined(attrs.order) ? attrs.order : 0;
var model = new WidgetDefinitionModel(attrs, {
parse: true, // make sure data is structured as expected
collection: self,
configModel: self._configModel,
mapId: self._mapId
});
return model;
},
initialize: function (models, opts) {
var self = this;
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
this._bindLayerStyleChanges();
this._attrsForThisTypeMap = {
formula: function (model) {
return {
column: model.get('column'),
operation: model.get('operation') || 'max'
};
},
category: function (model) {
var columnName = model.get('column');
return {
aggregation: model.get('aggregation') || 'count',
aggregation_column: model.get('aggregation_column') || columnName,
column: columnName,
widget_style_definition: model.get('widget_style_definition') || WidgetDefinitionModel.getDefaultWidgetStyle('category'),
auto_style_definition: undefined
};
},
histogram: function (model) {
return {
column: model.get('column'),
bins: model.get('bins') || 10,
column_type: 'number',
widget_style_definition: model.get('widget_style_definition') || WidgetDefinitionModel.getDefaultWidgetStyle('histogram'),
auto_style_definition: undefined
};
},
'time-series': function (model) {
return {
column: model.get('column'),
bins: model.get('bins') || 256,
aggregation: model.get('aggregation'),
column_type: self.getColumnType(model.get('column'), model.get('source')),
widget_style_definition: model.get('widget_style_definition') || WidgetDefinitionModel.getDefaultWidgetStyle('time-series')
};
}
};
},
url: function () {
var baseUrl = this._configModel.get('base_url');
return baseUrl + '/api/v3/maps/' + this._mapId + '/widgets';
},
parse: function (response) {
return response && response.widgets
? response.widgets
: [];
},
_bindLayerStyleChanges: function () {
this._layerDefinitionsCollection.bind('change:style_properties', this._onLayerStyleChanged, this);
},
_onLayerStyleChanged: function (layerDefModel) {
var styleModel = layerDefModel.styleModel;
var isAllowed = styleModel && styleModel.canApplyAutoStyle();
var affectedWidgets = this.where({ layer_id: layerDefModel.id });
_.each(affectedWidgets, function (widgetDefModel) {
var isNowAllowed = widgetDefModel.get('auto_style_allowed');
var willBeAllowed = isAllowed;
var attrs = {
auto_style_allowed: willBeAllowed
};
if (isNowAllowed !== willBeAllowed) {
// if autostyle is not allow, we should clean auto_style_definition
if (willBeAllowed === false) {
attrs = _.extend(attrs, { auto_style_definition: '' });
}
widgetDefModel.save(attrs);
}
});
},
addWidget: function (widgetModel, attrs) {
var self = this;
var ORDER_NUMBER_TO_APPEAR_ON_TOP = -1;
return new Promise(function (resolve, reject) {
_.extend(attrs, { order: ORDER_NUMBER_TO_APPEAR_ON_TOP });
self.create(attrs, {
wait: true,
success: function (model) {
resolve(model);
},
error: function (response, error) {
reject(error);
}
});
});
},
updateWidgetsOrder: function (numberOfWidgets) {
this.each(function (widgetDefinitionModel, index) {
widgetDefinitionModel.set({ order: index });
});
return this.saveAsync(numberOfWidgets);
},
saveAsync: function (updatedWidgets) {
var self = this;
this.trigger('loading', updatedWidgets);
return new Promise(function (resolve, reject) {
self.save({
wait: true,
success: function (collection) {
self.trigger('successAdd', updatedWidgets);
resolve(collection);
},
error: function (response, error) {
self.trigger('errorAdd', response);
reject(error);
}
});
});
},
save: function (options) {
options = options || {};
Backbone.sync('update', this, options);
},
attrsForThisType: function (newType, m) {
return this._attrsForThisTypeMap[newType](m);
},
resetableAttrsForTypeMap: function (type) {
switch (type) {
case 'formula':
return [];
case 'category':
return ['aggregation'];
case 'histogram':
return ['bins', 'column_type'];
case 'time-series':
return ['bins', 'aggregation', 'column_type'];
}
},
isThereTimeSeries: function (opts) {
opts = opts || {};
var timeSeries = opts.animated ? this.findWhere({ type: 'time-series', animated: opts.animated }) : this.findWhere({ type: 'time-series' });
return !!timeSeries;
},
isThereOtherWidgets: function () {
return !!this.find(function (widgetModel) {
return widgetModel.get('type') !== 'time-series';
});
},
_getNextOrder: function () {
if (this.isEmpty()) {
return 0;
} else {
var lastItemByOrder = this.max(function (mdl) {
return mdl.get('order');
});
return lastItemByOrder.get('order') + 1;
}
},
widgetsOwnedByLayer: function (layerId) {
var widgets = this.where({ layer_id: layerId });
return widgets.length;
},
getColumnType: function (columnName, source) {
var column;
var node = this._analysisDefinitionNodesCollection.get(source);
var schemaModel = node && node.querySchemaModel;
if (schemaModel && schemaModel.get('status') === 'fetched') {
column = schemaModel.columnsCollection.findWhere({ name: columnName });
}
return column && column.get('type');
}
});