Initial commit
This commit is contained in:
110
lib/assets/javascripts/builder/data/legends/legend-base-definition-model.js
Executable file
110
lib/assets/javascripts/builder/data/legends/legend-base-definition-model.js
Executable file
@@ -0,0 +1,110 @@
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var syncAbort = require('builder/data/backbone/sync-abort');
|
||||
var LegendsState = require('./legends-state');
|
||||
|
||||
/*
|
||||
Base model for a legend. It should have a reference to a layerDefinitionModel.
|
||||
*/
|
||||
module.exports = Backbone.Model.extend({
|
||||
defaults: {
|
||||
type: 'none',
|
||||
title: '',
|
||||
postHTMLSnippet: '',
|
||||
preHTMLSnippet: ''
|
||||
},
|
||||
|
||||
sync: syncAbort,
|
||||
|
||||
parse: function (r) {
|
||||
var attrs = _.extend({},
|
||||
_.omit(r, 'created_at', 'updated_at', 'definition', 'pre_html', 'post_html')
|
||||
);
|
||||
|
||||
if (r.conf && r.conf.columns) {
|
||||
attrs.customState = r.conf.columns;
|
||||
}
|
||||
|
||||
attrs.preHTMLSnippet = r.pre_html;
|
||||
attrs.postHTMLSnippet = r.post_html;
|
||||
return attrs;
|
||||
},
|
||||
|
||||
urlRoot: function () {
|
||||
var baseUrl = this.configModel.get('base_url');
|
||||
return baseUrl + '/api/v3/viz/' + this.vizId + '/layer/' + this.layerDefinitionModel.id + '/legends';
|
||||
},
|
||||
|
||||
initialize: function (attrs, opts) {
|
||||
if (!opts.layerDefinitionModel) throw new Error('layerDefinitionModel is required');
|
||||
if (!opts.configModel) throw new Error('configModel is required');
|
||||
if (!opts.vizId) throw new Error('vizId is required');
|
||||
|
||||
this.layerDefinitionModel = opts.layerDefinitionModel;
|
||||
this.configModel = opts.configModel;
|
||||
this.vizId = opts.vizId;
|
||||
},
|
||||
|
||||
getStyles: function () {
|
||||
return this.layerDefinitionModel && this.layerDefinitionModel.styleModel || null;
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
throw new Error('This model should not make any fetch calls. It should be created from the vizJSON.');
|
||||
},
|
||||
|
||||
getType: function () {
|
||||
return this.get('type');
|
||||
},
|
||||
|
||||
toJSON: function () {
|
||||
return _.extend(
|
||||
this.attributes,
|
||||
{
|
||||
type: this.getType()
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getAttributes: function () {
|
||||
return _.extend(
|
||||
{},
|
||||
_.pick(this.attributes, _.keys(this.defaults)),
|
||||
_.omit(this.attributes, 'pre_html', 'post_html', 'customState')
|
||||
);
|
||||
},
|
||||
|
||||
setAttributes: function (attrs) {
|
||||
// Store the real values
|
||||
LegendsState.set(this.layerDefinitionModel, this.get('type') || attrs.type, attrs);
|
||||
this.set(attrs);
|
||||
},
|
||||
|
||||
// Overriding set
|
||||
set: function (key, val, options) {
|
||||
var attrs;
|
||||
if (typeof key === 'object') {
|
||||
attrs = key;
|
||||
options = val;
|
||||
} else {
|
||||
(attrs = {})[key] = val;
|
||||
}
|
||||
|
||||
options || (options = {});
|
||||
|
||||
var layerDefinitionModel = this.layerDefinitionModel || options.layerDefinitionModel;
|
||||
var type = this.get('type') || attrs.type;
|
||||
|
||||
// Override attributes with the current custom state
|
||||
var state = LegendsState.get(layerDefinitionModel, type);
|
||||
var attributes = _.extend({}, attrs, {
|
||||
customState: _.keys(state)
|
||||
}, state);
|
||||
|
||||
return Backbone.Model.prototype.set.call(this, attributes, options);
|
||||
},
|
||||
|
||||
hasCustomHtml: function () {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-base-definition-model');
|
||||
var LegendColorHelper = require('builder/editor/layers/layer-content-views/legend/form/legend-color-helper');
|
||||
var DEFAULT_BUBBLES_COLOR = '#999999';
|
||||
|
||||
module.exports = LegendBaseDefModel.extend({
|
||||
defaults: _.extend({}, LegendBaseDefModel.prototype.defaults,
|
||||
{
|
||||
type: 'bubble',
|
||||
fillColor: DEFAULT_BUBBLES_COLOR,
|
||||
topLabel: '',
|
||||
bottomLabel: ''
|
||||
}
|
||||
),
|
||||
|
||||
parse: function (r, opts) {
|
||||
var attrs = LegendBaseDefModel.prototype.parse.call(this, r);
|
||||
|
||||
if (opts.layerDefinitionModel) {
|
||||
if (r.definition) {
|
||||
attrs.fillColor = r.definition.color;
|
||||
attrs.topLabel = r.definition.top_label;
|
||||
attrs.bottomLabel = r.definition.bottom_label;
|
||||
} else {
|
||||
attrs.fillColor = this._inheritStyleColor(opts.layerDefinitionModel.styleModel);
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
},
|
||||
|
||||
toJSON: function () {
|
||||
return _.extend(
|
||||
{},
|
||||
_.omit(this.attributes, 'fill', 'fillColor', 'topLabel', 'bottomLabel', 'postHTMLSnippet', 'preHTMLSnippet', 'customState'),
|
||||
{
|
||||
pre_html: this.get('preHTMLSnippet'),
|
||||
post_html: this.get('postHTMLSnippet')
|
||||
},
|
||||
{
|
||||
conf: {
|
||||
columns: this.get('customState')
|
||||
}
|
||||
},
|
||||
{
|
||||
definition: {
|
||||
color: this.get('fillColor'),
|
||||
top_label: this.get('topLabel'),
|
||||
bottom_label: this.get('bottomLabel')
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_inheritStyleColor: function (styleModel) {
|
||||
var fill = styleModel.get('fill');
|
||||
var stroke = styleModel.get('stroke');
|
||||
var color = (fill && fill.color) || (stroke && stroke.color);
|
||||
|
||||
if (color && (color.fixed || color.range)) {
|
||||
return LegendColorHelper.getBubbles(color).color.fixed;
|
||||
} else {
|
||||
return DEFAULT_BUBBLES_COLOR;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-base-definition-model');
|
||||
|
||||
module.exports = LegendBaseDefModel.extend({
|
||||
defaults: _.extend({}, LegendBaseDefModel.prototype.defaults,
|
||||
{
|
||||
type: 'category'
|
||||
}
|
||||
),
|
||||
|
||||
toJSON: function () {
|
||||
return _.extend(
|
||||
{},
|
||||
_.omit(this.attributes, 'postHTMLSnippet', 'preHTMLSnippet', 'customState'),
|
||||
{
|
||||
pre_html: this.get('preHTMLSnippet'),
|
||||
post_html: this.get('postHTMLSnippet')
|
||||
},
|
||||
{
|
||||
conf: {
|
||||
columns: this.get('customState')
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-base-definition-model');
|
||||
|
||||
module.exports = LegendBaseDefModel.extend({
|
||||
defaults: _.extend({}, LegendBaseDefModel.prototype.defaults,
|
||||
{
|
||||
type: 'choropleth',
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
leftLabel: '',
|
||||
rightLabel: ''
|
||||
}
|
||||
),
|
||||
|
||||
parse: function (r, opts) {
|
||||
var attrs = LegendBaseDefModel.prototype.parse.call(this, r);
|
||||
if (r.definition) {
|
||||
attrs.prefix = r.definition.prefix;
|
||||
attrs.suffix = r.definition.suffix;
|
||||
attrs.leftLabel = r.definition.left_label;
|
||||
attrs.rightLabel = r.definition.right_label;
|
||||
}
|
||||
return attrs;
|
||||
},
|
||||
|
||||
toJSON: function () {
|
||||
var definition = {
|
||||
prefix: this.get('prefix'),
|
||||
suffix: this.get('suffix'),
|
||||
left_label: this.get('leftLabel'),
|
||||
right_label: this.get('rightLabel')
|
||||
};
|
||||
|
||||
return _.extend(
|
||||
{},
|
||||
_.omit(this.attributes, 'prefix', 'suffix', 'leftLabel', 'rightLabel', 'postHTMLSnippet', 'preHTMLSnippet', 'customState'),
|
||||
{
|
||||
pre_html: this.get('preHTMLSnippet'),
|
||||
post_html: this.get('postHTMLSnippet')
|
||||
},
|
||||
{
|
||||
conf: {
|
||||
columns: this.get('customState')
|
||||
}
|
||||
},
|
||||
{
|
||||
definition: _.pick(definition, _.identity)
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-base-definition-model');
|
||||
|
||||
module.exports = LegendBaseDefModel.extend({
|
||||
defaults: _.extend({}, LegendBaseDefModel.prototype.defaults,
|
||||
{
|
||||
type: 'custom_choropleth',
|
||||
prefix: '',
|
||||
suffix: '',
|
||||
colors: [],
|
||||
leftLabel: '',
|
||||
rightLabel: ''
|
||||
}
|
||||
),
|
||||
|
||||
parse: function (r, opts) {
|
||||
var attrs = LegendBaseDefModel.prototype.parse.call(this, r);
|
||||
var fill;
|
||||
var stroke;
|
||||
var color;
|
||||
|
||||
if (r.definition) {
|
||||
attrs.colors = r.definition.colors;
|
||||
attrs.prefix = r.definition.prefix;
|
||||
attrs.suffix = r.definition.suffix;
|
||||
attrs.leftLabel = r.definition.left_label;
|
||||
attrs.rightLabel = r.definition.right_label;
|
||||
} else {
|
||||
fill = opts.layerDefinitionModel.styleModel.get('fill');
|
||||
stroke = opts.layerDefinitionModel.styleModel.get('stroke');
|
||||
color = fill.color || stroke.color;
|
||||
attrs.colors = this._inheritStyleColors(color);
|
||||
}
|
||||
return attrs;
|
||||
},
|
||||
|
||||
toJSON: function () {
|
||||
var definition = {
|
||||
prefix: this.get('prefix'),
|
||||
suffix: this.get('suffix'),
|
||||
left_label: this.get('leftLabel'),
|
||||
right_label: this.get('rightLabel'),
|
||||
colors: this.get('colors').map(function (item) {
|
||||
return {
|
||||
color: item.color
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
return _.extend(
|
||||
{},
|
||||
_.omit(this.attributes, 'prefix', 'suffix', 'leftLabel', 'rightLabel', 'colors', 'postHTMLSnippet', 'preHTMLSnippet', 'customState'),
|
||||
{
|
||||
pre_html: this.get('preHTMLSnippet'),
|
||||
post_html: this.get('postHTMLSnippet')
|
||||
},
|
||||
{
|
||||
conf: {
|
||||
columns: this.get('customState')
|
||||
}
|
||||
},
|
||||
{
|
||||
definition: _.pick(definition, _.identity)
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
_inheritStyleColors: function (color) {
|
||||
var range = 0;
|
||||
var colors = [];
|
||||
|
||||
if (color.range) {
|
||||
range = color.range.length;
|
||||
|
||||
colors = _.range(range).map(function (v, index) {
|
||||
return {
|
||||
color: color.range[index]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-base-definition-model');
|
||||
var StyleHelper = require('builder/helpers/style');
|
||||
|
||||
module.exports = LegendBaseDefModel.extend({
|
||||
defaults: _.extend({}, LegendBaseDefModel.prototype.defaults,
|
||||
{
|
||||
type: 'custom',
|
||||
items: [],
|
||||
html: ''
|
||||
}
|
||||
),
|
||||
|
||||
parse: function (r, opts) {
|
||||
var attrs = LegendBaseDefModel.prototype.parse.call(this, r);
|
||||
|
||||
if (r.definition) {
|
||||
attrs.items = r.definition.categories;
|
||||
attrs.html = r.definition.html || '';
|
||||
} else {
|
||||
attrs.items = StyleHelper.getStyleCategories(opts.layerDefinitionModel.styleModel);
|
||||
}
|
||||
attrs.type = 'custom';
|
||||
return attrs;
|
||||
},
|
||||
|
||||
toJSON: function () {
|
||||
var definition = {
|
||||
categories: this.get('items').map(function (item) {
|
||||
return {
|
||||
title: (item.title || '').toString(),
|
||||
color: item.color,
|
||||
icon: item.image || item.icon
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
if (this.hasCustomHtml()) {
|
||||
definition.html = this.get('html');
|
||||
}
|
||||
|
||||
return _.extend(
|
||||
{},
|
||||
_.omit(this.attributes, 'items', 'html', 'postHTMLSnippet', 'preHTMLSnippet', 'customState'),
|
||||
{
|
||||
pre_html: this.get('preHTMLSnippet'),
|
||||
post_html: this.get('postHTMLSnippet')
|
||||
},
|
||||
{
|
||||
conf: {
|
||||
columns: this.get('customState')
|
||||
}
|
||||
},
|
||||
{
|
||||
definition: definition
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
hasCustomHtml: function () {
|
||||
return this.get('html') !== '';
|
||||
}
|
||||
});
|
||||
104
lib/assets/javascripts/builder/data/legends/legend-definitions-collection.js
Executable file
104
lib/assets/javascripts/builder/data/legends/legend-definitions-collection.js
Executable file
@@ -0,0 +1,104 @@
|
||||
var Backbone = require('backbone');
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-base-definition-model');
|
||||
var layerTypesAndKinds = require('builder/data/layer-types-and-kinds');
|
||||
|
||||
var CategoryModel = require('./legend-category-definition-model');
|
||||
var BubbleModel = require('./legend-bubble-definition-model');
|
||||
var ChoroplethModel = require('./legend-choropleth-definition-model');
|
||||
var CustomChoroplethModel = require('./legend-custom-choropleth-definition-model');
|
||||
var CustomModel = require('./legend-custom-definition-model');
|
||||
var TorqueModel = require('./legend-torque-definition-model');
|
||||
|
||||
var LEGEND_MODEL_TYPE = {
|
||||
'bubble': BubbleModel,
|
||||
'category': CategoryModel,
|
||||
'choropleth': ChoroplethModel,
|
||||
'custom_choropleth': CustomChoroplethModel,
|
||||
'custom': CustomModel,
|
||||
'html': CustomModel,
|
||||
'torque': TorqueModel
|
||||
};
|
||||
|
||||
module.exports = Backbone.Collection.extend({
|
||||
model: LegendBaseDefModel,
|
||||
|
||||
initialize: function (models, options) {
|
||||
if (!options.configModel) throw new Error('configModel is required');
|
||||
if (!options.layerDefinitionsCollection) throw new Error('layerDefinitionsCollection is required');
|
||||
if (!options.vizId) throw new Error('vizId is required');
|
||||
|
||||
this.configModel = options.configModel;
|
||||
this.layerDefinitionsCollection = options.layerDefinitionsCollection;
|
||||
this.vizId = options.vizId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Intended to be called from entry point, to make sure initial layers are taken into account
|
||||
*/
|
||||
resetByData: function (vizJSON) {
|
||||
var models = [];
|
||||
var layers = _.filter(vizJSON.layers, function (layer) {
|
||||
return this._isDataLayer(layer.type);
|
||||
}, this);
|
||||
|
||||
_.each(layers, function (layer) {
|
||||
var layerDefModel = this._findLayerDefinitionModel(layer.id);
|
||||
var legends = [];
|
||||
if (layer.legends) {
|
||||
legends = layer.legends.map(function (legend) {
|
||||
var Klass = LEGEND_MODEL_TYPE[legend.type];
|
||||
|
||||
return new Klass(legend, {
|
||||
layerDefinitionModel: layerDefModel,
|
||||
configModel: this.configModel,
|
||||
vizId: this.vizId,
|
||||
parse: true
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
|
||||
models.push(legends);
|
||||
}, this);
|
||||
|
||||
this.reset(_.flatten(models));
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
throw new Error('This collection should not make any fetch calls. It should be populated from the vizJSON.');
|
||||
},
|
||||
|
||||
_isDataLayer: function (layerType) {
|
||||
return layerTypesAndKinds.isCartoDBType(layerType) ||
|
||||
layerTypesAndKinds.isTorqueType(layerType);
|
||||
},
|
||||
|
||||
_findLayerDefinitionModel: function (id) {
|
||||
return this.layerDefinitionsCollection.findWhere({id: id});
|
||||
},
|
||||
|
||||
findByLayerDefModel: function (layerDefModel) {
|
||||
var id = layerDefModel.id;
|
||||
return this.filter(function (legendDefModel) {
|
||||
var layerDefModel = legendDefModel.layerDefinitionModel;
|
||||
return layerDefModel.id === id;
|
||||
});
|
||||
},
|
||||
|
||||
findByLayerDefModelAndType: function (layerDefModel, type) {
|
||||
var id = layerDefModel.id;
|
||||
return this.find(function (legendDefModel) {
|
||||
var layerDefModel = legendDefModel.layerDefinitionModel;
|
||||
return layerDefModel.id === id && legendDefModel.get('type') === type;
|
||||
});
|
||||
},
|
||||
|
||||
findByLayerDefModelAndTypes: function (layerDefModel, types) {
|
||||
var id = layerDefModel.id;
|
||||
return this.filter(function (legendDefModel) {
|
||||
var layerDefModel = legendDefModel.layerDefinitionModel;
|
||||
var type = legendDefModel.get('type');
|
||||
return layerDefModel.id === id && types.indexOf(type) !== -1;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
var _ = require('underscore');
|
||||
var LegendBaseDefModel = require('./legend-custom-definition-model');
|
||||
|
||||
module.exports = LegendBaseDefModel.extend({
|
||||
defaults: function () {
|
||||
return _.extend({}, LegendBaseDefModel.prototype.defaults,
|
||||
{
|
||||
type: 'torque',
|
||||
items: [],
|
||||
html: ''
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
parse: function (r, opts) {
|
||||
var attrs = LegendBaseDefModel.prototype.parse.call(this, r, opts);
|
||||
attrs.type = 'torque';
|
||||
return attrs;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
var LEGENDS_METADATA = {
|
||||
bubble: {
|
||||
legendType: 'size'
|
||||
},
|
||||
category: {
|
||||
legendType: 'color'
|
||||
},
|
||||
choropleth: {
|
||||
legendType: 'color'
|
||||
},
|
||||
custom: {
|
||||
legendType: 'color'
|
||||
},
|
||||
custom_choropleth: {
|
||||
legendType: 'color'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = LEGENDS_METADATA;
|
||||
72
lib/assets/javascripts/builder/data/legends/legends-state.js
Executable file
72
lib/assets/javascripts/builder/data/legends/legends-state.js
Executable file
@@ -0,0 +1,72 @@
|
||||
var _ = require('underscore');
|
||||
var legendsMetadata = require('./legends-metadata');
|
||||
|
||||
var CUSTOM_ATTRIBUTES = ['title'];
|
||||
var instance;
|
||||
var legends;
|
||||
|
||||
var State = (function () {
|
||||
var getType = function (type) {
|
||||
var legend = legendsMetadata[type];
|
||||
return legend && legend.legendType;
|
||||
};
|
||||
|
||||
var onLayerAdded = function (layer) {
|
||||
instance[layer.id] = {};
|
||||
};
|
||||
|
||||
var onLayerRemoved = function (layer) {
|
||||
delete instance[layer.id];
|
||||
};
|
||||
|
||||
return {
|
||||
init: function (layersDefinitionCollection, legendsDefinitionCollection) {
|
||||
if (!instance) {
|
||||
instance = {};
|
||||
layersDefinitionCollection.on('add', onLayerAdded);
|
||||
layersDefinitionCollection.on('remove', onLayerRemoved);
|
||||
legends = legendsDefinitionCollection;
|
||||
this.reset();
|
||||
}
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
legends.each(function (legend) {
|
||||
var layer = legend.layerDefinitionModel;
|
||||
if (!instance[layer.id]) {
|
||||
instance[layer.id] = {};
|
||||
}
|
||||
|
||||
var legendType = getType(legend.get('type'));
|
||||
if (!instance[layer.id][legendType]) {
|
||||
instance[layer.id][legendType] = {};
|
||||
}
|
||||
|
||||
var state = _.pick(legend.attributes, legend.attributes.conf.columns);
|
||||
instance[layer.id][legendType] = state;
|
||||
});
|
||||
},
|
||||
|
||||
set: function (layer, type, attrs) {
|
||||
var attributes = _.pick(attrs, CUSTOM_ATTRIBUTES);
|
||||
var legendType = getType(type);
|
||||
if (instance && legendType) {
|
||||
if (!instance[layer.id]) {
|
||||
instance[layer.id] = {};
|
||||
}
|
||||
instance[layer.id][legendType] = attributes;
|
||||
}
|
||||
},
|
||||
|
||||
get: function (layer, type) {
|
||||
var legendType = getType(type);
|
||||
return instance && legendType && instance[layer.id] && instance[layer.id][legendType];
|
||||
},
|
||||
|
||||
getInstance: function () {
|
||||
return instance;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
module.exports = State;
|
||||
Reference in New Issue
Block a user