Refactor around how visualizations/*.js are required (#913)

* Refactor around how visualizations/*.js are required

* Reactifying FilterBox further

* Fixing the auto-refresh on filtering events

* Fixing preselected filters
This commit is contained in:
Maxime Beauchemin 2016-08-11 21:39:10 -07:00 committed by GitHub
parent 198226a39f
commit e243a14c64
21 changed files with 468 additions and 359 deletions

View File

@ -154,7 +154,7 @@ function dashboardContainer(dashboardData) {
refreshExcept(sliceId) { refreshExcept(sliceId) {
const immune = this.metadata.filter_immune_slices || []; const immune = this.metadata.filter_immune_slices || [];
this.slices.forEach(function (slice) { this.slices.forEach(function (slice) {
if (slice.data.sliceId !== sliceId && immune.indexOf(slice.data.sliceId) === -1) { if (slice.data.slice_id !== sliceId && immune.indexOf(slice.data.sliceId) === -1) {
slice.render(); slice.render();
} }
}); });

View File

@ -475,9 +475,6 @@ $(document).ready(function () {
initExploreView(); initExploreView();
// Dynamically register this visualization
px.registerViz(data.viz_name || 'table');
slice = px.Slice(data); slice = px.Slice(data);
$('.slice').data('slice', slice); $('.slice').data('slice', slice);

View File

@ -1,210 +1,19 @@
import $ from 'jquery'; import $ from 'jquery';
const d3 = require('d3');
const Mustache = require('mustache'); const Mustache = require('mustache');
const utils = require('./utils'); const utils = require('./utils');
// vis sources // vis sources
/* eslint camel-case: 0 */ /* eslint camel-case: 0 */
const sourceMap = { import vizMap from '../../visualizations/main.js';
area: 'nvd3_vis.js',
bar: 'nvd3_vis.js',
bubble: 'nvd3_vis.js',
big_number: 'big_number.js',
big_number_total: 'big_number.js',
compare: 'nvd3_vis.js',
dist_bar: 'nvd3_vis.js',
directed_force: 'directed_force.js',
filter_box: 'filter_box.js',
heatmap: 'heatmap.js',
iframe: 'iframe.js',
line: 'nvd3_vis.js',
markup: 'markup.js',
separator: 'markup.js',
para: 'parallel_coordinates.js',
pie: 'nvd3_vis.js',
box_plot: 'nvd3_vis.js',
pivot_table: 'pivot_table.js',
sankey: 'sankey.js',
sunburst: 'sunburst.js',
table: 'table.js',
word_cloud: 'word_cloud.js',
world_map: 'world_map.js',
treemap: 'treemap.js',
cal_heatmap: 'cal_heatmap.js',
horizon: 'horizon.js',
mapbox: 'mapbox.jsx',
histogram: 'histogram.js',
};
const color = function () {
// Color related utility functions go in this object
const bnbColors = [
'#ff5a5f', // rausch
'#7b0051', // hackb
'#007A87', // kazan
'#00d1c1', // babu
'#8ce071', // lima
'#ffb400', // beach
'#b4a76c', // barol
'#ff8083',
'#cc0086',
'#00a1b3',
'#00ffeb',
'#bbedab',
'#ffd266',
'#cbc29a',
'#ff3339',
'#ff1ab1',
'#005c66',
'#00b3a5',
'#55d12e',
'#b37e00',
'#988b4e',
];
const spectrums = {
blue_white_yellow: [
'#00d1c1',
'white',
'#ffb400',
],
fire: [
'white',
'yellow',
'red',
'black',
],
white_black: [
'white',
'black',
],
black_white: [
'black',
'white',
],
};
const colorBnb = function () {
// Color factory
const seen = {};
return function (s) {
if (!s) {
return;
}
let stringifyS = String(s);
// next line is for caravel series that should have the same color
stringifyS = stringifyS.replace('---', '');
if (seen[stringifyS] === undefined) {
seen[stringifyS] = Object.keys(seen).length;
}
/* eslint consistent-return: 0 */
return this.bnbColors[seen[stringifyS] % this.bnbColors.length];
};
};
const colorScalerFactory = function (colors, data, accessor) {
// Returns a linear scaler our of an array of color
if (!Array.isArray(colors)) {
/* eslint no-param-reassign: 0 */
colors = spectrums[colors];
}
let ext = [
0,
1,
];
if (data !== undefined) {
ext = d3.extent(data, accessor);
}
const points = [];
const chunkSize = (ext[1] - ext[0]) / colors.length;
$.each(colors, function (i) {
points.push(i * chunkSize);
});
return d3.scale.linear().domain(points).range(colors);
};
return {
bnbColors,
category21: colorBnb(),
colorScalerFactory,
};
};
/* eslint wrap-iife: 0*/ /* eslint wrap-iife: 0*/
const px = function () { const px = function () {
const visualizations = {};
let slice; let slice;
function getParam(name) { function getParam(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); const formattedName = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); const regex = new RegExp('[\\?&]' + formattedName + '=([^&#]*)');
const results = regex.exec(location.search); const results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
} }
function UTC(dttm) {
return new Date(
dttm.getUTCFullYear(),
dttm.getUTCMonth(),
dttm.getUTCDate(),
dttm.getUTCHours(),
dttm.getUTCMinutes(),
dttm.getUTCSeconds()
);
}
const tickMultiFormat = d3.time.format.multi([
[
'.%L',
function (d) {
return d.getMilliseconds();
},
],
// If there are millisections, show only them
[
':%S',
function (d) {
return d.getSeconds();
},
],
// If there are seconds, show only them
[
'%a %b %d, %I:%M %p',
function (d) {
return d.getMinutes() !== 0;
},
],
// If there are non-zero minutes, show Date, Hour:Minute [AM/PM]
[
'%a %b %d, %I %p',
function (d) {
return d.getHours() !== 0;
},
],
// If there are hours that are multiples of 3, show date and AM/PM
[
'%a %b %d',
function (d) {
return d.getDate() !== 1;
},
],
// If not the first of the month, do "month day, year."
[
'%B %Y',
function (d) {
return d.getMonth() !== 0 && d.getDate() === 1;
},
],
// If the first of the month, do "month day, year."
[
'%Y',
function () {
return true;
},
], // fall back on month, year
]);
function formatDate(dttm) {
const d = UTC(new Date(dttm));
// d = new Date(d.getTime() - 1 * 60 * 60 * 1000);
return tickMultiFormat(d);
}
function timeFormatFactory(d3timeFormat) {
const f = d3.time.format(d3timeFormat);
return function (dttm) {
const d = UTC(new Date(dttm));
return f(d);
};
}
function initFavStars() { function initFavStars() {
const baseUrl = '/caravel/favstar/'; const baseUrl = '/caravel/favstar/';
// Init star behavihor for favorite // Init star behavihor for favorite
@ -267,12 +76,12 @@ const px = function () {
containerId, containerId,
selector, selector,
querystring(params) { querystring(params) {
params = params || {}; const newParams = params || {};
const parser = document.createElement('a'); const parser = document.createElement('a');
parser.href = data.json_endpoint; parser.href = data.json_endpoint;
if (dashboard !== undefined) { if (dashboard !== undefined) {
const flts = const flts =
params.extraFilters === false ? '' : newParams.extraFilters === false ? '' :
encodeURIComponent(JSON.stringify(dashboard.filters)); encodeURIComponent(JSON.stringify(dashboard.filters));
qrystr = parser.search + '&extra_filters=' + flts; qrystr = parser.search + '&extra_filters=' + flts;
} else if ($('#query').length === 0) { } else if ($('#query').length === 0) {
@ -293,10 +102,10 @@ const px = function () {
return Mustache.render(s, context); return Mustache.render(s, context);
}, },
jsonEndpoint(params) { jsonEndpoint(params) {
params = params || {}; const newParams = params || {};
const parser = document.createElement('a'); const parser = document.createElement('a');
parser.href = data.json_endpoint; parser.href = data.json_endpoint;
let endpoint = parser.pathname + this.querystring({ extraFilters: params.extraFilters }); let endpoint = parser.pathname + this.querystring({ extraFilters: newParams.extraFilters });
endpoint += '&json=true'; endpoint += '&json=true';
endpoint += '&force=' + this.force; endpoint += '&force=' + this.force;
return endpoint; return endpoint;
@ -413,9 +222,10 @@ const px = function () {
}, },
render(force) { render(force) {
if (force === undefined) { if (force === undefined) {
force = false; this.force = false;
} else {
this.force = force;
} }
this.force = force;
token.find('img.loading').show(); token.find('img.loading').show();
container.css('height', this.height()); container.css('height', this.height());
dttm = 0; dttm = 0;
@ -457,32 +267,14 @@ const px = function () {
} }
}, },
}; };
const visType = data.form_data.viz_type; slice.viz = vizMap[data.form_data.viz_type](slice);
px.registerViz(visType);
slice.viz = visualizations[data.form_data.viz_type](slice);
return slice; return slice;
}; };
function registerViz(name) {
const visSource = sourceMap[name];
if (visSource) {
/* eslint global-require: 0 */
const visFactory = require('../../visualizations/' + visSource);
if (typeof visFactory === 'function') {
visualizations[name] = visFactory;
}
} else {
throw new Error('require(' + name + ') failed.');
}
}
// Export public functions // Export public functions
return { return {
color: color(),
formatDate,
getParam, getParam,
initFavStars, initFavStars,
registerViz,
Slice, Slice,
timeFormatFactory,
}; };
}(); }();
module.exports = px; module.exports = px;

View File

@ -0,0 +1,85 @@
import $ from 'jquery';
const d3 = require('d3');
// Color related utility functions go in this object
export const bnbColors = [
'#ff5a5f', // rausch
'#7b0051', // hackb
'#007A87', // kazan
'#00d1c1', // babu
'#8ce071', // lima
'#ffb400', // beach
'#b4a76c', // barol
'#ff8083',
'#cc0086',
'#00a1b3',
'#00ffeb',
'#bbedab',
'#ffd266',
'#cbc29a',
'#ff3339',
'#ff1ab1',
'#005c66',
'#00b3a5',
'#55d12e',
'#b37e00',
'#988b4e',
];
const spectrums = {
blue_white_yellow: [
'#00d1c1',
'white',
'#ffb400',
],
fire: [
'white',
'yellow',
'red',
'black',
],
white_black: [
'white',
'black',
],
black_white: [
'black',
'white',
],
};
export const category21 = (function () {
// Color factory
const seen = {};
return function (s) {
if (!s) {
return;
}
let stringifyS = String(s);
// next line is for caravel series that should have the same color
stringifyS = stringifyS.replace('---', '');
if (seen[stringifyS] === undefined) {
seen[stringifyS] = Object.keys(seen).length;
}
/* eslint consistent-return: 0 */
return bnbColors[seen[stringifyS] % bnbColors.length];
};
}());
export const colorScalerFactory = function (colors, data, accessor) {
// Returns a linear scaler our of an array of color
if (!Array.isArray(colors)) {
/* eslint no-param-reassign: 0 */
colors = spectrums[colors];
}
let ext = [0, 1];
if (data !== undefined) {
ext = d3.extent(data, accessor);
}
const points = [];
const chunkSize = (ext[1] - ext[0]) / colors.length;
$.each(colors, function (i) {
points.push(i * chunkSize);
});
return d3.scale.linear().domain(points).range(colors);
};

View File

@ -0,0 +1,74 @@
const d3 = require('d3');
function UTC(dttm) {
return new Date(
dttm.getUTCFullYear(),
dttm.getUTCMonth(),
dttm.getUTCDate(),
dttm.getUTCHours(),
dttm.getUTCMinutes(),
dttm.getUTCSeconds()
);
}
export const tickMultiFormat = d3.time.format.multi([
[
'.%L',
function (d) {
return d.getMilliseconds();
},
],
// If there are millisections, show only them
[
':%S',
function (d) {
return d.getSeconds();
},
],
// If there are seconds, show only them
[
'%a %b %d, %I:%M %p',
function (d) {
return d.getMinutes() !== 0;
},
],
// If there are non-zero minutes, show Date, Hour:Minute [AM/PM]
[
'%a %b %d, %I %p',
function (d) {
return d.getHours() !== 0;
},
],
// If there are hours that are multiples of 3, show date and AM/PM
[
'%a %b %d',
function (d) {
return d.getDate() !== 1;
},
],
// If not the first of the month, do "month day, year."
[
'%B %Y',
function (d) {
return d.getMonth() !== 0 && d.getDate() === 1;
},
],
// If the first of the month, do "month day, year."
[
'%Y',
function () {
return true;
},
], // fall back on month, year
]);
export const formatDate = function (dttm) {
const d = UTC(new Date(dttm));
// d = new Date(d.getTime() - 1 * 60 * 60 * 1000);
return tickMultiFormat(d);
};
export const timeFormatFactory = function (d3timeFormat) {
const f = d3.time.format(d3timeFormat);
return function (dttm) {
const d = UTC(new Date(dttm));
return f(d);
};
};

View File

@ -1,5 +1,5 @@
const $ = require('jquery');
const d3 = require('d3'); const d3 = require('d3');
const $ = require('jquery');
/* /*
Utility function that takes a d3 svg:text selection and a max width, and splits the Utility function that takes a d3 svg:text selection and a max width, and splits the
text's text across multiple tspan lines such that any given line does not exceed max width text's text across multiple tspan lines such that any given line does not exceed max width
@ -7,7 +7,7 @@ const d3 = require('d3');
If text does not span multiple lines AND adjustedY is passed, If text does not span multiple lines AND adjustedY is passed,
will set the text to the passed val will set the text to the passed val
*/ */
function wrapSvgText(text, width, adjustedY) { export function wrapSvgText(text, width, adjustedY) {
const lineHeight = 1; const lineHeight = 1;
// ems // ems
text.each(function () { text.each(function () {

View File

@ -59,6 +59,7 @@
"nvd3": "1.8.4", "nvd3": "1.8.4",
"react": "^15.2.1", "react": "^15.2.1",
"react-bootstrap": "^0.28.3", "react-bootstrap": "^0.28.3",
"react-bootstrap-datetimepicker": "0.0.22",
"react-bootstrap-table": "^2.3.7", "react-bootstrap-table": "^2.3.7",
"react-dom": "^0.14.8", "react-dom": "^0.14.8",
"react-grid-layout": "^0.12.3", "react-grid-layout": "^0.12.3",

View File

@ -107,7 +107,7 @@
.btn + .btn-group, .btn + .btn-group,
.btn-group + .btn, .btn-group + .btn,
.btn-group + .btn-group { .btn-group + .btn-group {
margin-left: -1; margin-left: -2;
} }
&-vertical { &-vertical {

View File

@ -0,0 +1,93 @@
// @mistercrunch
@select-primary-color: black;
/**
* React Select
* ============
* Created by Jed Watson and Joss Mackison for KeystoneJS, http://www.keystonejs.com/
* https://twitter.com/jedwatson https://twitter.com/jossmackison https://twitter.com/keystonejs
* MIT License: https://github.com/keystonejs/react-select
*/
// Variables
// ------------------------------
// common
//@select-primary-color: #007eff;
// control options
@select-input-bg: #fff;
@select-input-bg-disabled: #f9f9f9;
@select-input-border-color: #ccc;
@select-input-border-radius: 4px;
@select-input-border-focus: @select-primary-color;
@select-input-border-width: 1px;
@select-input-height: 36px;
@select-input-internal-height: (@select-input-height - (@select-input-border-width * 2));
@select-input-placeholder: #aaa;
@select-text-color: #333;
@select-link-hover-color: @select-input-border-focus;
@select-padding-vertical: 8px;
@select-padding-horizontal: 10px;
// menu options
@select-menu-zindex: 1;
@select-menu-max-height: 200px;
@select-option-color: lighten(@select-text-color, 20%);
@select-option-bg: @select-input-bg;
@select-option-focused-color: @select-text-color;
@select-option-focused-bg: fade(@select-primary-color, 8%);
@select-option-focused-bg-fb: mix(@select-primary-color, @select-option-bg, 8%); // Fallback color for IE 8
@select-option-selected-color: @select-text-color;
@select-option-selected-bg: fade(@select-primary-color, 4%);
@select-option-selected-bg-fb: mix(@select-primary-color, @select-option-bg, 4%); // Fallback color for IE 8
@select-option-disabled-color: lighten(@select-text-color, 60%);
@select-noresults-color: lighten(@select-text-color, 40%);
// clear "x" button
@select-clear-size: floor((@select-input-height / 2));
@select-clear-color: #999;
@select-clear-hover-color: #D0021B; // red
@select-clear-width: (@select-input-internal-height / 2);
// arrow indicator
@select-arrow-color: #999;
@select-arrow-color-hover: #666;
@select-arrow-width: 5px;
// loading indicator
@select-loading-size: 16px;
@select-loading-color: @select-text-color;
@select-loading-color-bg: @select-input-border-color;
// multi-select item
@select-item-font-size: .9em;
@select-item-bg: fade(@select-primary-color, 8%);
@select-item-bg-fb: mix(@select-primary-color, @select-input-bg, 8%); // Fallback color for IE 8
@select-item-color: @select-primary-color;
@select-item-border-color: fade(@select-primary-color, 24%);
@select-item-border-color-fb: mix(@select-primary-color, @select-input-bg, 24%); // Fallback color for IE 8
@select-item-hover-color: darken(@select-item-color, 5%);
@select-item-hover-bg: darken(@select-item-bg, 5%);
@select-item-hover-bg-fb: mix(darken(@select-primary-color, 5%), @select-item-bg-fb, 8%); // Fallback color for IE 8
@select-item-disabled-color: #333;
@select-item-disabled-bg: #fcfcfc;
@select-item-disabled-border-color: darken(@select-item-disabled-bg, 10%);
@select-item-border-radius: 2px;
@select-item-gutter: 5px;
@select-item-padding-horizontal: 5px;
@select-item-padding-vertical: 2px;
// imports
// @mistercrunch: these were altered to point to react-select/less
@import "../../node_modules/react-select/less/control.less";
@import "../../node_modules/react-select/less/menu.less";
@import "../../node_modules/react-select/less/mixins.less";
@import "../../node_modules/react-select/less/multi.less";
@import "../../node_modules/react-select/less/spinner.less";

View File

@ -4,7 +4,7 @@ var d3 = window.d3 || require('d3');
// CSS // CSS
require('./big_number.css'); require('./big_number.css');
var px = require('../javascripts/modules/caravel.js'); import { formatDate } from '../javascripts/modules/dates'
function bigNumberVis(slice) { function bigNumberVis(slice) {
var div = d3.select(slice.selector); var div = d3.select(slice.selector);
@ -140,7 +140,7 @@ function bigNumberVis(slice) {
.scale(scale_x) .scale(scale_x)
.orient('bottom') .orient('bottom')
.ticks(4) .ticks(4)
.tickFormat(px.formatDate); .tickFormat(formatDate);
g.call(x_axis); g.call(x_axis);
g.attr('transform', 'translate(0,' + (height - margin) + ')'); g.attr('transform', 'translate(0,' + (height - margin) + ')');

View File

@ -4,19 +4,26 @@
} }
.dashboard .filter_box .slice_container > div { .dashboard .filter_box .slice_container > div {
padding-top: 0; padding-top: 0;
} }
ul.select2-results li.select2-highlighted div.filter_box{ ul.select2-results li.select2-highlighted div.filter_box{
color: black; color: black;
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
border-color: #666; border-color: #666;
} }
ul.select2-results div.filter_box{ ul.select2-results div.filter_box{
color: black; color: black;
border-style: solid; border-style: solid;
border-width: 1px; border-width: 1px;
border-color: transparent; border-color: transparent;
}
.filter_box .slice_container {
padding: 10px;
overflow: visible !important;
}
.filter_box:hover {
z-index: 1000;
} }

View File

@ -1,92 +0,0 @@
// JS
var $ = window.$ = require('jquery');
var jQuery = window.jQuery = $;
var d3 = window.d3 || require('d3');
// CSS
require('./filter_box.css');
require('../javascripts/caravel-select2.js');
function filterBox(slice) {
var filtersObj = {};
var d3token = d3.select(slice.selector);
var fltChanged = function () {
var val = $(this).val();
var vals = [];
if (val !== '') {
vals = val.split(',');
}
slice.setFilter($(this).attr('name'), vals);
};
var refresh = function () {
d3token.selectAll("*").remove();
var container = d3token
.append('div')
.classed('padded', true);
var preSelectDict = slice.getFilters() || {};
$.getJSON(slice.jsonEndpoint({
// filter box should ignore the filters
// otherwise there will be only a few options in the dropdown menu
extraFilters: false,
}), function (payload) {
var maxes = {};
for (var filter in payload.data) {
var data = payload.data[filter];
maxes[filter] = d3.max(data, function (d) {
return d.metric;
});
var id = 'fltbox__' + filter;
var div = container.append('div');
div.append("label").text(filter);
div.append('div')
.attr('name', filter)
.classed('form-control', true)
.attr('multiple', '')
.attr('id', id);
filtersObj[filter] = $('#' + id).select2({
placeholder: "Select [" + filter + ']',
containment: 'parent',
dropdownAutoWidth: true,
data: data,
multiple: true,
formatResult: select2Formatter,
})
.on('change', fltChanged);
var preSelect = preSelectDict[filter];
if (preSelect !== undefined) {
filtersObj[filter].select2('val', preSelect);
}
}
slice.done(payload);
function select2Formatter(result, container /*, query, escapeMarkup*/) {
var perc = Math.round((result.metric / maxes[result.filter]) * 100);
var style = 'padding: 2px 5px;';
style += "background-image: ";
style += "linear-gradient(to right, lightgrey, lightgrey " + perc + "%, rgba(0,0,0,0) " + perc + "%";
$(container).attr('style', 'padding: 0px; background: white;');
$(container).addClass('filter_box');
return '<div style="' + style + '"><span>' + result.text + '</span></div>';
}
})
.fail(function (xhr) {
slice.error(xhr.responseText, xhr);
});
};
return {
render: refresh,
resize: refresh,
};
}
module.exports = filterBox;

View File

@ -0,0 +1,122 @@
// JS
const $ = window.$ = require('jquery');
const d3 = window.d3 || require('d3');
import React from 'react';
import ReactDOM from 'react-dom';
import Select from 'react-select';
import '../stylesheets/react-select/select.less';
import './filter_box.css';
class FilterBox extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedValues: props.origSelectedValues,
};
}
render() {
const filters = Object.keys(this.props.filtersChoices).map((filter) => {
const data = this.props.filtersChoices[filter];
const id = 'fltbox__' + filter;
const maxes = {};
maxes[filter] = d3.max(data, function (d) {
return d.metric;
});
return (
<div>
{filter}
<Select
placeholder={`Select [${filter}]`}
key={filter}
multi={true}
value={this.state.selectedValues[filter]}
options={data.map((opt) => {
const perc = Math.round((opt.metric / maxes[opt.filter]) * 100);
const backgroundImage = (
'linear-gradient(to right, lightgrey, ' +
`lightgrey ${perc}%, rgba(0,0,0,0) ${perc}%`
);
const style = {
backgroundImage,
padding:'2px 5px',
};
return { value: opt.id, label: opt.id, style };
})}
onChange={(selectedOptions) => {
let vals;
if (selectedOptions) {
vals = selectedOptions.map((opt) => opt.value);
} else {
vals = null;
}
const selectedValues = this.state.selectedValues;
selectedValues[filter] = vals;
this.setState({ selectedValues });
this.props.onChange(filter, vals);
}}
/>
</div>
);
const preSelect = preSelectDict[filter];
if (preSelect !== undefined) {
filtersObj[filter].select2('val', preSelect);
}
});
return (
<div>
{filters}
</div>
);
}
}
FilterBox.propTypes = {
origSelectedValues: React.PropTypes.objectOf(React.PropTypes.array),
filtersChoices: React.PropTypes.objectOf(React.PropTypes.array),
onChange: React.PropTypes.function,
};
FilterBox.defaultProps = {
origSelectedValues: {},
onChange: function () {},
};
function filterBox(slice) {
const filtersObj = {};
const d3token = d3.select(slice.selector);
const refresh = function () {
d3token.selectAll('*').remove();
const container = d3token
.append('div')
.classed('padded', true);
const preSelectDict = slice.getFilters() || {};
// filter box should ignore the dashboard's filters
const url = slice.jsonEndpoint({ extraFilters: false});
$.getJSON(url, (payload) => {
ReactDOM.render(
(
<FilterBox
filtersChoices={payload.data}
onChange={slice.setFilter}
origSelectedValues={slice.getFilters() || {}}
/>
),
document.getElementById(slice.containerId)
);
slice.done(payload);
})
.fail(function (xhr) {
slice.error(xhr.responseText, xhr);
});
};
return {
render: refresh,
resize: () => {},
};
}
module.exports = filterBox;

View File

@ -1,7 +1,7 @@
// JS // JS
var $ = window.$ || require('jquery'); var $ = window.$ || require('jquery');
var px = window.px || require('../javascripts/modules/caravel.js');
var d3 = require('d3'); var d3 = require('d3');
import { colorScalerFactory } from '../javascripts/modules/colors'
d3.tip = require('d3-tip'); //using window.d3 doesn't capture events properly bc of multiple instances d3.tip = require('d3-tip'); //using window.d3 doesn't capture events properly bc of multiple instances
@ -84,7 +84,7 @@ function heatmapVis(slice) {
Y = 1; Y = 1;
var heatmapDim = [xRbScale.domain().length, yRbScale.domain().length]; var heatmapDim = [xRbScale.domain().length, yRbScale.domain().length];
var color = px.color.colorScalerFactory(fd.linear_color_scheme); var color = colorScalerFactory(fd.linear_color_scheme);
var scale = [ var scale = [
d3.scale.linear() d3.scale.linear()

View File

@ -0,0 +1,31 @@
const vizMap = {
filter_box: require('./filter_box.jsx'),
area: require('./nvd3_vis.js'),
bar: require('./nvd3_vis.js'),
big_number: require('./big_number.js'),
big_number_total: require('./big_number.js'),
box_plot: require('./nvd3_vis.js'),
bubble: require('./nvd3_vis.js'),
cal_heatmap: require('./cal_heatmap.js'),
compare: require('./nvd3_vis.js'),
directed_force: require('./directed_force.js'),
dist_bar: require('./nvd3_vis.js'),
heatmap: require('./heatmap.js'),
histogram: require('./histogram.js'),
horizon: require('./horizon.js'),
iframe: require('./iframe.js'),
line: require('./nvd3_vis.js'),
mapbox: require('./mapbox.jsx'),
markup: require('./markup.js'),
para: require('./parallel_coordinates.js'),
pie: require('./nvd3_vis.js'),
pivot_table: require('./pivot_table.js'),
sankey: require('./sankey.js'),
separator: require('./markup.js'),
sunburst: require('./sunburst.js'),
table: require('./table.js'),
treemap: require('./treemap.js'),
word_cloud: require('./word_cloud.js'),
world_map: require('./world_map.js'),
};
export default vizMap;

View File

@ -1,6 +1,7 @@
// JS // JS
var d3 = window.d3 || require('d3'); var d3 = window.d3 || require('d3');
var px = window.px || require('../javascripts/modules/caravel.js'); import { category21 } from '../javascripts/modules/colors'
import { timeFormatFactory, formatDate } from '../javascripts/modules/dates'
var nv = require('nvd3'); var nv = require('nvd3');
// CSS // CSS
@ -203,14 +204,14 @@ function nvd3Vis(slice) {
if (fd.x_log_scale) { if (fd.x_log_scale) {
chart.xScale(d3.scale.log()); chart.xScale(d3.scale.log());
} }
var xAxisFormatter = null; var xAxisFormatter;
if (viz_type === 'bubble') { if (viz_type === 'bubble') {
xAxisFormatter = d3.format('.3s'); xAxisFormatter = d3.format('.3s');
} else if (fd.x_axis_format === 'smart_date') { } else if (fd.x_axis_format === 'smart_date') {
xAxisFormatter = px.formatDate; xAxisFormatter = formatDate;
chart.xAxis.tickFormat(xAxisFormatter); chart.xAxis.tickFormat(xAxisFormatter);
} else if (fd.x_axis_format !== undefined) { } else if (fd.x_axis_format !== undefined) {
xAxisFormatter = px.timeFormatFactory(fd.x_axis_format); xAxisFormatter = timeFormatFactory(fd.x_axis_format);
chart.xAxis.tickFormat(xAxisFormatter); chart.xAxis.tickFormat(xAxisFormatter);
} }
@ -222,9 +223,9 @@ function nvd3Vis(slice) {
if (viz_type === 'bubble') { if (viz_type === 'bubble') {
chart.xAxis.tickFormat(d3.format('.3s')); chart.xAxis.tickFormat(d3.format('.3s'));
} else if (fd.x_axis_format === 'smart_date') { } else if (fd.x_axis_format === 'smart_date') {
chart.xAxis.tickFormat(px.formatDate); chart.xAxis.tickFormat(formatDate);
} else if (fd.x_axis_format !== undefined) { } else if (fd.x_axis_format !== undefined) {
chart.xAxis.tickFormat(px.timeFormatFactory(fd.x_axis_format)); chart.xAxis.tickFormat(timeFormatFactory(fd.x_axis_format));
} }
if (chart.yAxis !== undefined) { if (chart.yAxis !== undefined) {
chart.yAxis.tickFormat(d3.format('.3s')); chart.yAxis.tickFormat(d3.format('.3s'));
@ -238,7 +239,7 @@ function nvd3Vis(slice) {
} }
} }
chart.color(function (d, i) { chart.color(function (d, i) {
return px.color.category21(d[colorKey]); return category21(d[colorKey]);
}); });
if (fd.x_axis_label && fd.x_axis_label !== '' && chart.xAxis) { if (fd.x_axis_label && fd.x_axis_label !== '' && chart.xAxis) {

View File

@ -1,7 +1,7 @@
// CSS // CSS
require('./sankey.css'); require('./sankey.css');
// JS // JS
var px = window.px || require('../javascripts/modules/caravel.js'); import { category21 } from '../javascripts/modules/colors'
var d3 = window.d3 || require('d3'); var d3 = window.d3 || require('d3');
d3.sankey = require('d3-sankey').sankey; d3.sankey = require('d3-sankey').sankey;
@ -94,7 +94,7 @@ function sankeyVis(slice) {
}) })
.attr("width", sankey.nodeWidth()) .attr("width", sankey.nodeWidth())
.style("fill", function (d) { .style("fill", function (d) {
d.color = px.color.category21(d.name.replace(/ .*/, "")); d.color = category21(d.name.replace(/ .*/, ""));
return d.color; return d.color;
}) })
.style("stroke", function (d) { .style("stroke", function (d) {

View File

@ -1,6 +1,6 @@
var d3 = window.d3 || require('d3'); var d3 = window.d3 || require('d3');
var px = require('../javascripts/modules/caravel.js'); import { category21 } from '../javascripts/modules/colors'
var wrapSvgText = require('../javascripts/modules/utils.js').wrapSvgText; import { wrapSvgText } from '../javascripts/modules/utils'
require('./sunburst.css'); require('./sunburst.css');
@ -132,7 +132,7 @@ function sunburstVis(slice) {
.attr("d", arc) .attr("d", arc)
.attr("fill-rule", "evenodd") .attr("fill-rule", "evenodd")
.style("fill", function (d) { .style("fill", function (d) {
return colorByCategory ? px.color.category21(d.name) : colorScale(d.m2 / d.m1); return colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1);
}) })
.style("opacity", 1) .style("opacity", 1)
.on("mouseenter", mouseenter); .on("mouseenter", mouseenter);
@ -263,7 +263,7 @@ function sunburstVis(slice) {
entering.append("svg:polygon") entering.append("svg:polygon")
.attr("points", breadcrumbPoints) .attr("points", breadcrumbPoints)
.style("fill", function (d) { .style("fill", function (d) {
return colorByCategory ? px.color.category21(d.name) : colorScale(d.m2 / d.m1); return colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1);
}); });
entering.append("svg:text") entering.append("svg:text")
@ -272,7 +272,7 @@ function sunburstVis(slice) {
.attr("dy", "0.35em") .attr("dy", "0.35em")
.style("fill", function (d) { .style("fill", function (d) {
// Make text white or black based on the lightness of the background // Make text white or black based on the lightness of the background
var col = d3.hsl(colorByCategory ? px.color.category21(d.name) : colorScale(d.m2 / d.m1)); var col = d3.hsl(colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1));
return col.l < 0.5 ? 'white' : 'black'; return col.l < 0.5 ? 'white' : 'black';
}) })
.attr("class", "step-label") .attr("class", "step-label")

View File

@ -1,12 +1,11 @@
var $ = window.$ = require('jquery'); var $ = window.$ = require('jquery');
var jQuery = window.jQuery = $;
var d3 = require('d3'); var d3 = require('d3');
var px = window.px || require('../javascripts/modules/caravel.js'); import { fixDataTableBodyHeight } from '../javascripts/modules/utils'
var utils = require('../javascripts/modules/utils.js'); import { timeFormatFactory, formatDate } from '../javascripts/modules/dates'
require('./table.css'); require('./table.css');
require('datatables.net-bs'); require('datatables.net-bs');
require('../node_modules/datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css'); require('datatables-bootstrap3-plugin/media/css/datatables-bootstrap3.css');
function tableVis(slice) { function tableVis(slice) {
var fC = d3.format('0,000'); var fC = d3.format('0,000');
@ -46,9 +45,9 @@ function tableVis(slice) {
} }
if (json.form_data.table_timestamp_format === 'smart_date') { if (json.form_data.table_timestamp_format === 'smart_date') {
timestampFormatter = px.formatDate; timestampFormatter = formatDate;
} else if (json.form_data.table_timestamp_format !== undefined) { } else if (json.form_data.table_timestamp_format !== undefined) {
timestampFormatter = px.timeFormatFactory(json.form_data.table_timestamp_format); timestampFormatter = timeFormatFactory(json.form_data.table_timestamp_format);
} }
var div = d3.select(slice.selector); var div = d3.select(slice.selector);
@ -134,7 +133,7 @@ function tableVis(slice) {
scrollCollapse: true, scrollCollapse: true,
scrollX: true, scrollX: true,
}); });
utils.fixDataTableBodyHeight( fixDataTableBodyHeight(
slice.container.find('.dataTables_wrapper'), height); slice.container.find('.dataTables_wrapper'), height);
// Sorting table by main column // Sorting table by main column
if (form_data.metrics.length > 0) { if (form_data.metrics.length > 0) {

View File

@ -1,6 +1,6 @@
// JS // JS
var d3 = window.d3 || require('d3'); var d3 = window.d3 || require('d3');
var px = window.px || require('../javascripts/modules/caravel.js'); import { category21 } from '../javascripts/modules/colors'
// CSS // CSS
require('./treemap.css'); require('./treemap.css');
@ -185,9 +185,8 @@ function treemap(slice) {
.attr("dy", "1.0em") .attr("dy", "1.0em")
.text(function (d) { return formatNumber(d.value); }); .text(function (d) { return formatNumber(d.value); });
t.call(text); t.call(text);
g.selectAll("rect") g.selectAll("rect")
.style("fill", function (d) { return px.color.category21(d.name); }); .style("fill", function (d) { return category21(d.name); });
return g; return g;
}; };

View File

@ -1,6 +1,6 @@
var px = window.px || require('../javascripts/modules/caravel.js');
var d3 = window.d3 || require('d3'); var d3 = window.d3 || require('d3');
var cloudLayout = require('d3-cloud'); import cloudLayout from 'd3-cloud'
import { category21 } from '../javascripts/modules/colors'
function wordCloudChart(slice) { function wordCloudChart(slice) {
var chart = d3.select(slice.selector); var chart = d3.select(slice.selector);
@ -68,7 +68,7 @@ function wordCloudChart(slice) {
}) })
.style("font-family", "Impact") .style("font-family", "Impact")
.style("fill", function (d) { .style("fill", function (d) {
return px.color.category21(d.text); return category21(d.text);
}) })
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("transform", function (d) { .attr("transform", function (d) {