Skip to content

Commit

Permalink
Merge pull request #420 from redbearsam/d3fc_plugin
Browse files Browse the repository at this point in the history
D3fc plugin
  • Loading branch information
texodus authored Feb 26, 2019
2 parents 03ae7c8 + 0474191 commit d0bfe8e
Show file tree
Hide file tree
Showing 45 changed files with 2,701 additions and 15 deletions.
1 change: 1 addition & 0 deletions examples/simple/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<a href="streaming.html">High-frequency streaming random data example</a>
<a href="citibike.html">NYC Citibike inventory example</a>
<a href="csv.html">User-provided CSV example</a>
<a href="superstore-d3fc.html">Superstore example using D3FC Bar/Column charts</a>
</div>

</body>
Expand Down
50 changes: 50 additions & 0 deletions examples/simple/superstore-d3fc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!--
Copyright (c) 2017, the Perspective Authors.
This file is part of the Perspective library, distributed under the terms of
the Apache License 2.0. The full license can be found in the LICENSE file.
-->

<!DOCTYPE html>
<html>

<head>

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

<script src="perspective.view.js"></script>
<script src="hypergrid.plugin.js"></script>
<script src="d3fc.plugin.js"></script>

<script src="perspective.js"></script>

<link rel='stylesheet' href="index.css">
<link rel='stylesheet' href="material.css" is="custom-style">

</head>

<body>

<perspective-viewer view="d3_y_bar" row-pivots='["Sub-Category"]' sort='[["Profit", "desc"]]' columns='["Profit"]'>

</perspective-viewer>

<script>
window.addEventListener('WebComponentsReady', function() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'superstore.arrow', true);
xhr.responseType = "arraybuffer"
xhr.onload = function() {
var el = document.getElementsByTagName('perspective-viewer')[0];
el.load(xhr.response);
el.toggleConfig();
}
xhr.send(null);
});
</script>

</body>

</html>
22 changes: 22 additions & 0 deletions packages/perspective-viewer-d3fc/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports = {
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
],
"sourceType": "unambiguous",
"plugins": [
["@babel/plugin-proposal-decorators", {"legacy": true}],
"transform-custom-element-classes",
"@babel/plugin-transform-runtime",
[
"@babel/plugin-transform-for-of",
{
"loose": true
}
]
]
};
51 changes: 51 additions & 0 deletions packages/perspective-viewer-d3fc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"name": "@jpmorganchase/perspective-viewer-d3fc",
"version": "0.2.10",
"description": "Perspective.js",
"main": "src/js/plugin/plugin.js",
"files": [
"build/**/*",
"src/**/*",
"babel.config.js"
],
"scripts": {
"bench": "npm-run-all bench:build bench:run",
"bench:build": "echo \"No Benchmarks\"",
"bench:run": "echo \"No Benchmarks\"",
"build": "webpack --color --config src/config/d3fc.plugin.config.js",
"test:build": "cp test/html/* build",
"watch": "webpack --color --watch --config src/config/d3fc.plugin.config.js",
"test:run": "jest --silent --color 2>&1",
"test": "npm-run-all test:build test:run",
"clean": "find build -mindepth 1 -delete",
"clean:screenshots": "find screenshots/ \\( -name *.diff.png -o -name *.failed.png \\) -mindepth 1 -delete"
},
"jest": {
"roots": [
"test/js"
],
"verbose": true,
"testURL": "http://localhost/",
"transform": {},
"automock": false
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/jpmorganchase/perspective"
},
"author": "",
"license": "Apache-2.0",
"dependencies": {
"@jpmorganchase/perspective": "^0.2.10",
"@jpmorganchase/perspective-viewer": "^0.2.10",
"babel-runtime": "^6.26.0",
"chroma-js": "^1.3.4",
"d3": "^5.7.0",
"d3-svg-legend": "^2.25.6",
"d3fc": "^14.0.25",
"gradient-parser": "0.1.5"
}
}
12 changes: 12 additions & 0 deletions packages/perspective-viewer-d3fc/src/config/d3fc.plugin.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const path = require("path");
const common = require("@jpmorganchase/perspective/src/config/common.config.js");

module.exports = Object.assign({}, common(), {
entry: "./src/js/plugin/plugin.js",
output: {
filename: "d3fc.plugin.js",
library: "perspective-view-d3fc",
libraryTarget: "umd",
path: path.resolve(__dirname, "../../build")
}
});
4 changes: 4 additions & 0 deletions packages/perspective-viewer-d3fc/src/html/d3fc-chart.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<template id="perspective-d3fc-chart">
<div id="container" class="chart">
</div>
</template>
5 changes: 5 additions & 0 deletions packages/perspective-viewer-d3fc/src/html/d3fc.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template id="perspective-d3fc">
<div id="container">

</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<span id="up-arrow">&#9650;</span>
<span id="page-text"></span>
<span id="down-arrow">&#9660;</span>
3 changes: 3 additions & 0 deletions packages/perspective-viewer-d3fc/src/html/tooltip.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<ul id="cross-values"></ul>
<ul id="split-values"></ul>
<ul id="data-values"></ul>
74 changes: 74 additions & 0 deletions packages/perspective-viewer-d3fc/src/js/axis/crossAxis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/******************************************************************************
*
* Copyright (c) 2017, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
import * as d3 from "d3";
import * as fc from "d3fc";
import minBandwidth from "./minBandwidth";
import withoutTicks from "./withoutTicks";

const AXIS_TYPES = {
none: "none",
ordinal: "ordinal",
time: "time",
linear: "linear"
};

export const scale = settings => {
switch (axisType(settings)) {
case AXIS_TYPES.none:
return withoutTicks(defaultScaleBand());
case AXIS_TYPES.time:
return d3.scaleTime();
case AXIS_TYPES.linear:
return d3.scaleLinear();
default:
return defaultScaleBand();
}
};

const defaultScaleBand = () => minBandwidth(d3.scaleBand());

export const domain = settings => {
const accessData = extent => {
return extent.accessors([labelFunction(settings)])(settings.data);
};
switch (axisType(settings)) {
case AXIS_TYPES.time:
return accessData(fc.extentTime());
case AXIS_TYPES.linear:
return accessData(fc.extentLinear());
default:
return settings.data.map(labelFunction(settings));
}
};

export const labelFunction = settings => {
switch (axisType(settings)) {
case AXIS_TYPES.none:
return d => d.__ROW_PATH__[0];
case AXIS_TYPES.time:
return d => new Date(d.__ROW_PATH__[0]);
case AXIS_TYPES.linear:
return d => d.__ROW_PATH__[0];
default:
return d => d.__ROW_PATH__.join(",");
}
};

export const label = settings => settings.crossValues.map(v => v.name).join(", ");

const axisType = settings => {
if (settings.crossValues.length === 0) {
return AXIS_TYPES.none;
} else if (settings.crossValues.length === 1) {
if (settings.crossValues[0].type === "datetime") {
return AXIS_TYPES.time;
}
}
return AXIS_TYPES.ordinal;
};
40 changes: 40 additions & 0 deletions packages/perspective-viewer-d3fc/src/js/axis/mainAxis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/******************************************************************************
*
* Copyright (c) 2017, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
import * as d3 from "d3";

export const scale = () => d3.scaleLinear();

export const domain = (settings, data, valueName = "mainValue") => {
const extent = getDataExtentFromArray(data, valueName);
return [extent[0] > 0 ? 0 : extent[0] * 1.1, extent[1] < 0 ? 0 : extent[1] * 1.1];
};

const getDataExtentFromArray = (array, valueName) => {
const dataExtent = array.map(v => getDataExtentFromValue(v, valueName));
const extent = flattenExtent(dataExtent);
return extent;
};

const getDataExtentFromValue = (value, valueName) => {
if (Array.isArray(value)) {
return getDataExtentFromArray(value, valueName);
}
return [value[valueName], value[valueName]];
};

export const label = settings => settings.mainValues.map(v => v.name).join(", ");

function flattenExtent(array) {
const withUndefined = fn => (a, b) => {
if (a === undefined) return b;
if (b === undefined) return a;
return fn(a, b);
};
return array.reduce((r, v) => [withUndefined(Math.min)(r[0], v[0]), withUndefined(Math.max)(r[1], v[1])], [undefined, undefined]);
}
29 changes: 29 additions & 0 deletions packages/perspective-viewer-d3fc/src/js/axis/minBandwidth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/******************************************************************************
*
* Copyright (c) 2017, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
import {rebindAll} from "d3fc";

const MIN_BANDWIDTH = 1;

export default adaptee => {
const minBandwidth = arg => {
return adaptee(arg);
};

rebindAll(minBandwidth, adaptee);

minBandwidth.bandwidth = (...args) => {
if (!args.length) {
return Math.max(adaptee.bandwidth(), MIN_BANDWIDTH);
}
adaptee.bandwidth(...args);
return minBandwidth;
};

return minBandwidth;
};
23 changes: 23 additions & 0 deletions packages/perspective-viewer-d3fc/src/js/axis/withoutTicks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/******************************************************************************
*
* Copyright (c) 2017, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
import {rebindAll} from "d3fc";

export default adaptee => {
const withoutTicks = arg => {
return adaptee(arg);
};

rebindAll(withoutTicks, adaptee);

withoutTicks.ticks = function() {
return [];
};

return withoutTicks;
};
54 changes: 54 additions & 0 deletions packages/perspective-viewer-d3fc/src/js/charts/bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/******************************************************************************
*
* Copyright (c) 2017, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
import * as fc from "d3fc";
import * as crossAxis from "../axis/crossAxis";
import * as mainAxis from "../axis/mainAxis";
import {barSeries} from "../series/barSeries";
import {seriesColours} from "../series/seriesColours";
import {groupAndStackData} from "../data/groupAndStackData";
import {legend, filterData} from "../legend/legend";
import {withGridLines} from "../gridlines/gridlines";

function barChart(container, settings) {
const data = groupAndStackData(settings, filterData(settings));
const colour = seriesColours(settings);
legend(container, settings, colour);

const series = fc
.seriesSvgMulti()
.mapping((data, index) => data[index])
.series(
data.map(() =>
barSeries(settings, colour)
.align("left")
.orient("horizontal")
)
);

const chart = fc
.chartSvgCartesian(mainAxis.scale(settings), crossAxis.scale(settings))
.xDomain(mainAxis.domain(settings, data))
.xLabel(mainAxis.label(settings))
.yDomain(crossAxis.domain(settings, data))
.yOrient("left")
.yLabel(crossAxis.label(settings))
.plotArea(withGridLines(series).orient("horizontal"));

chart.yPadding && chart.yPadding(0.5);

// render
container.datum(data).call(chart);
}
barChart.plugin = {
type: "d3_x_bar",
name: "[d3fc] X Bar Chart",
max_size: 25000
};

export default barChart;
Loading

0 comments on commit d0bfe8e

Please sign in to comment.