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) {
const immune = this.metadata.filter_immune_slices || [];
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();
}
});

View File

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

View File

@ -1,210 +1,19 @@
import $ from 'jquery';
const d3 = require('d3');
const Mustache = require('mustache');
const utils = require('./utils');
// vis sources
/* eslint camel-case: 0 */
const sourceMap = {
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,
};
};
import vizMap from '../../visualizations/main.js';
/* eslint wrap-iife: 0*/
const px = function () {
const visualizations = {};
let slice;
function getParam(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
const formattedName = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + formattedName + '=([^&#]*)');
const results = regex.exec(location.search);
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() {
const baseUrl = '/caravel/favstar/';
// Init star behavihor for favorite
@ -267,12 +76,12 @@ const px = function () {
containerId,
selector,
querystring(params) {
params = params || {};
const newParams = params || {};
const parser = document.createElement('a');
parser.href = data.json_endpoint;
if (dashboard !== undefined) {
const flts =
params.extraFilters === false ? '' :
newParams.extraFilters === false ? '' :
encodeURIComponent(JSON.stringify(dashboard.filters));
qrystr = parser.search + '&extra_filters=' + flts;
} else if ($('#query').length === 0) {
@ -293,10 +102,10 @@ const px = function () {
return Mustache.render(s, context);
},
jsonEndpoint(params) {
params = params || {};
const newParams = params || {};
const parser = document.createElement('a');
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 += '&force=' + this.force;
return endpoint;
@ -413,9 +222,10 @@ const px = function () {
},
render(force) {
if (force === undefined) {
force = false;
this.force = false;
} else {
this.force = force;
}
this.force = force;
token.find('img.loading').show();
container.css('height', this.height());
dttm = 0;
@ -457,32 +267,14 @@ const px = function () {
}
},
};
const visType = data.form_data.viz_type;
px.registerViz(visType);
slice.viz = visualizations[data.form_data.viz_type](slice);
slice.viz = vizMap[data.form_data.viz_type](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
return {
color: color(),
formatDate,
getParam,
initFavStars,
registerViz,
Slice,
timeFormatFactory,
};
}();
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 $ = require('jquery');
/*
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
@ -7,7 +7,7 @@ const d3 = require('d3');
If text does not span multiple lines AND adjustedY is passed,
will set the text to the passed val
*/
function wrapSvgText(text, width, adjustedY) {
export function wrapSvgText(text, width, adjustedY) {
const lineHeight = 1;
// ems
text.each(function () {

View File

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

View File

@ -107,7 +107,7 @@
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group {
margin-left: -1;
margin-left: -2;
}
&-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
require('./big_number.css');
var px = require('../javascripts/modules/caravel.js');
import { formatDate } from '../javascripts/modules/dates'
function bigNumberVis(slice) {
var div = d3.select(slice.selector);
@ -140,7 +140,7 @@ function bigNumberVis(slice) {
.scale(scale_x)
.orient('bottom')
.ticks(4)
.tickFormat(px.formatDate);
.tickFormat(formatDate);
g.call(x_axis);
g.attr('transform', 'translate(0,' + (height - margin) + ')');

View File

@ -4,19 +4,26 @@
}
.dashboard .filter_box .slice_container > div {
padding-top: 0;
padding-top: 0;
}
ul.select2-results li.select2-highlighted div.filter_box{
color: black;
border-width: 1px;
border-style: solid;
border-color: #666;
color: black;
border-width: 1px;
border-style: solid;
border-color: #666;
}
ul.select2-results div.filter_box{
color: black;
border-style: solid;
border-width: 1px;
border-color: transparent;
color: black;
border-style: solid;
border-width: 1px;
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
var $ = window.$ || require('jquery');
var px = window.px || require('../javascripts/modules/caravel.js');
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
@ -84,7 +84,7 @@ function heatmapVis(slice) {
Y = 1;
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 = [
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
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');
// CSS
@ -203,14 +204,14 @@ function nvd3Vis(slice) {
if (fd.x_log_scale) {
chart.xScale(d3.scale.log());
}
var xAxisFormatter = null;
var xAxisFormatter;
if (viz_type === 'bubble') {
xAxisFormatter = d3.format('.3s');
} else if (fd.x_axis_format === 'smart_date') {
xAxisFormatter = px.formatDate;
xAxisFormatter = formatDate;
chart.xAxis.tickFormat(xAxisFormatter);
} else if (fd.x_axis_format !== undefined) {
xAxisFormatter = px.timeFormatFactory(fd.x_axis_format);
xAxisFormatter = timeFormatFactory(fd.x_axis_format);
chart.xAxis.tickFormat(xAxisFormatter);
}
@ -222,9 +223,9 @@ function nvd3Vis(slice) {
if (viz_type === 'bubble') {
chart.xAxis.tickFormat(d3.format('.3s'));
} else if (fd.x_axis_format === 'smart_date') {
chart.xAxis.tickFormat(px.formatDate);
chart.xAxis.tickFormat(formatDate);
} 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) {
chart.yAxis.tickFormat(d3.format('.3s'));
@ -238,7 +239,7 @@ function nvd3Vis(slice) {
}
}
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) {

View File

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

View File

@ -1,6 +1,6 @@
var d3 = window.d3 || require('d3');
var px = require('../javascripts/modules/caravel.js');
var wrapSvgText = require('../javascripts/modules/utils.js').wrapSvgText;
import { category21 } from '../javascripts/modules/colors'
import { wrapSvgText } from '../javascripts/modules/utils'
require('./sunburst.css');
@ -132,7 +132,7 @@ function sunburstVis(slice) {
.attr("d", arc)
.attr("fill-rule", "evenodd")
.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)
.on("mouseenter", mouseenter);
@ -263,7 +263,7 @@ function sunburstVis(slice) {
entering.append("svg:polygon")
.attr("points", breadcrumbPoints)
.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")
@ -272,7 +272,7 @@ function sunburstVis(slice) {
.attr("dy", "0.35em")
.style("fill", function (d) {
// 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';
})
.attr("class", "step-label")

View File

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

View File

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

View File

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