lint fixes

This commit is contained in:
bkmartinjr
2018-09-20 14:52:17 -04:00
committed by Colin Megill
parent d9a75fcd10
commit 4543b002e3
6 changed files with 94 additions and 145 deletions
+9 -25
View File
@@ -5,17 +5,8 @@ import React from "react";
import _ from "lodash"; import _ from "lodash";
import { connect } from "react-redux"; import { connect } from "react-redux";
import styles from "./parallelCoordinates.css";
import SectionHeader from "../framework/sectionHeader";
import setupParallelCoordinates from "./setupParallelCoordinates";
import drawAxes from "./drawAxes";
import drawLinesCanvas from "./drawLinesCanvas";
import HistogramBrush from "./histogramBrush"; import HistogramBrush from "./histogramBrush";
import { margin, width, height, createDimensions } from "./util";
@connect(state => { @connect(state => {
const metadata = _.get(state.controls.world, "obsAnnotations", null); const metadata = _.get(state.controls.world, "obsAnnotations", null);
const ranges = _.get(state.controls.world, "summary.obs", null); const ranges = _.get(state.controls.world, "summary.obs", null);
@@ -29,35 +20,29 @@ import { margin, width, height, createDimensions } from "./util";
}; };
}) })
class Continuous extends React.Component { class Continuous extends React.Component {
constructor(props) {
super(props);
this.state = {
svg: null,
ctx: null,
axes: null,
dimensions: null
};
}
handleBrushAction(selection) { handleBrushAction(selection) {
this.props.dispatch({ const { dispatch } = this.props;
dispatch({
type: "continuous selection using parallel coords brushing", type: "continuous selection using parallel coords brushing",
data: selection data: selection
}); });
} }
handleColorAction(key) { handleColorAction(key) {
this.props.dispatch({ const { dispatch, ranges } = this.props;
dispatch({
type: "color by continuous metadata", type: "color by continuous metadata",
colorAccessor: key, colorAccessor: key,
rangeMaxForColorAccessor: this.props.ranges[key].range.max rangeMaxForColorAccessor: ranges[key].range.max
}); });
} }
render() { render() {
const { ranges } = this.props;
return ( return (
<div> <div>
{_.map(this.props.ranges, (value, key) => { {_.map(ranges, (value, key) => {
const isColorField = key.includes("color") || key.includes("Color"); const isColorField = key.includes("color") || key.includes("Color");
if (value.range && key !== "name" && !isColorField) { if (value.range && key !== "name" && !isColorField) {
return ( return (
@@ -68,6 +53,7 @@ class Continuous extends React.Component {
/> />
); );
} }
return null;
})} })}
</div> </div>
); );
@@ -75,5 +61,3 @@ class Continuous extends React.Component {
} }
export default Continuous; export default Continuous;
// <SectionHeader text="Continuous Metadata"/>
+10 -15
View File
@@ -1,4 +1,5 @@
// jshint esversion: 6 // jshint esversion: 6
import * as d3 from "d3";
import styles from "./parallelCoordinates.css"; import styles from "./parallelCoordinates.css";
import { yAxis, brushstart } from "./util"; import { yAxis, brushstart } from "./util";
@@ -19,13 +20,11 @@ const drawAxes = (
******************************************/ ******************************************/
function brush() { function brush() {
var actives = []; const actives = [];
svg svg
.selectAll(".parcoords_axis .parcoords_brush") .selectAll(".parcoords_axis .parcoords_brush")
.filter(function(d) { .filter(() => d3.brushSelection(this))
return d3.brushSelection(this); .each(d => {
})
.each(function(d) {
actives.push({ actives.push({
dimension: d, dimension: d,
extent: d3.brushSelection(this) extent: d3.brushSelection(this)
@@ -35,20 +34,18 @@ const drawAxes = (
handleBrushAction(actives); handleBrushAction(actives);
} }
var axes = svg const axes = svg
.selectAll(".parcoords_axis") .selectAll(".parcoords_axis")
.data(dimensions) .data(dimensions)
.enter() .enter()
.append("g") .append("g")
.attr("class", `${styles.axis} parcoords_axis`) .attr("class", `${styles.axis} parcoords_axis`)
.attr("transform", (d, i) => { .attr("transform", (d, i) => `translate(${xscale(i)})`);
return "translate(" + xscale(i) + ")";
});
axes axes
.append("g") .append("g")
.each(function(d) { .each(d => {
var renderAxis = const renderAxis =
"axis" in d "axis" in d
? d.axis.scale(d.scale) // custom axis ? d.axis.scale(d.scale) // custom axis
: yAxis.scale(d.scale); // default axis : yAxis.scale(d.scale); // default axis
@@ -60,15 +57,13 @@ const drawAxes = (
}) })
.attr("class", styles.title) .attr("class", styles.title)
.attr("text-anchor", "start") .attr("text-anchor", "start")
.text(function(d) { .text(d => ("description" in d ? `${d.description} 🖌️` : `${d.key} 🖌️`));
return "description" in d ? d.description + " 🖌️" : d.key + " 🖌️";
});
// Add and store a brush for each axis. // Add and store a brush for each axis.
axes axes
.append("g") .append("g")
.attr("class", `${styles.brush} parcoords_brush`) .attr("class", `${styles.brush} parcoords_brush`)
.each(function(d) { .each(d => {
d3.select(this).call( d3.select(this).call(
(d.brush = d3 (d.brush = d3
.brushY() .brushY()
@@ -10,54 +10,46 @@ import renderQueue from "../../util/renderQueue";
****************************************** ******************************************
******************************************/ ******************************************/
const drawLinesCanvas = ( const drawLinesCanvas = (ctx, dimensions, xscale) => d => {
ctx, ctx.globalAlpha = 0.1;
dimensions,
xscale,
colorAccessor,
colorScale
) => {
return d => {
ctx.globalAlpha = 0.1;
if (d["__selected__"]) { if (d.__selected__) {
ctx.strokeStyle = d["__color__"]; ctx.strokeStyle = d.__color__;
} else { } else {
return;
}
ctx.beginPath();
const coords = project(d, dimensions, xscale);
coords.forEach((p, i) => {
// this tricky bit avoids rendering null values as 0
if (p === null) {
// this bit renders horizontal lines on the previous/next
// dimensions, so that sandwiched null values are visible
if (i > 0) {
const prev = coords[i - 1];
if (prev !== null) {
ctx.moveTo(prev[0], prev[1]);
ctx.lineTo(prev[0] + 6, prev[1]);
}
}
if (i < coords.length - 1) {
const next = coords[i + 1];
if (next !== null) {
ctx.moveTo(next[0] - 6, next[1]);
}
}
return; return;
} }
ctx.beginPath(); if (i === 0) {
var coords = project(d, dimensions, xscale); ctx.moveTo(p[0], p[1]);
coords.forEach((p, i) => { return;
// this tricky bit avoids rendering null values as 0 }
if (p === null) {
// this bit renders horizontal lines on the previous/next
// dimensions, so that sandwiched null values are visible
if (i > 0) {
var prev = coords[i - 1];
if (prev !== null) {
ctx.moveTo(prev[0], prev[1]);
ctx.lineTo(prev[0] + 6, prev[1]);
}
}
if (i < coords.length - 1) {
var next = coords[i + 1];
if (next !== null) {
ctx.moveTo(next[0] - 6, next[1]);
}
}
return;
}
if (i == 0) { ctx.lineTo(p[0], p[1]);
ctx.moveTo(p[0], p[1]); });
return; ctx.stroke();
}
ctx.lineTo(p[0], p[1]);
});
ctx.stroke();
};
}; };
const drawCellLinesUsingRenderQueue = ( const drawCellLinesUsingRenderQueue = (
@@ -12,14 +12,12 @@ import * as d3 from "d3";
import memoize from "memoize-one"; import memoize from "memoize-one";
import * as globals from "../../globals"; import * as globals from "../../globals";
@connect(state => { @connect(state => ({
return { initializeRanges: _.get(state.controls.world, "summary.obs"),
initializeRanges: _.get(state.controls.world, "summary.obs"), colorAccessor: state.controls.colorAccessor,
colorAccessor: state.controls.colorAccessor, colorScale: state.controls.colorScale,
colorScale: state.controls.colorScale, obsAnnotations: _.get(state.controls.world, "obsAnnotations", null)
obsAnnotations: _.get(state.controls.world, "obsAnnotations", null) }))
};
})
class HistogramBrush extends React.Component { class HistogramBrush extends React.Component {
calcHistogramCache = memoize((obsAnnotations, metadataField, ranges) => { calcHistogramCache = memoize((obsAnnotations, metadataField, ranges) => {
// recalculate expensive stuff // recalculate expensive stuff
@@ -101,18 +99,10 @@ class HistogramBrush extends React.Component {
.enter() .enter()
.append("rect") .append("rect")
.attr("class", "bar") .attr("class", "bar")
.attr("x", function(d) { .attr("x", d => x(d.x0) + 1)
return x(d.x0) + 1; .attr("y", d => y(d.length / numValues))
}) .attr("width", d => Math.abs(x(d.x1) - x(d.x0) - 1))
.attr("y", function(d) { .attr("height", d => y(0) - y(d.length / numValues));
return y(d.length / numValues);
})
.attr("width", function(d) {
return Math.abs(x(d.x1) - x(d.x0) - 1);
})
.attr("height", function(d) {
return y(0) - y(d.length / numValues);
});
if (!this.state.brush && !this.state.axis) { if (!this.state.brush && !this.state.axis) {
const brush = d3 const brush = d3
@@ -122,20 +112,14 @@ class HistogramBrush extends React.Component {
.call( .call(
d3 d3
.brushX() .brushX()
.on( .on("end", this.onBrush(metadataField, x.invert).bind(this))
"end",
this.onBrush(this.props.metadataField, x.invert).bind(this)
)
); );
const xAxis = d3 const xAxis = d3
.select(svgRef) .select(svgRef)
.append("g") .append("g")
.attr("class", "axis axis--x") .attr("class", "axis axis--x")
.attr( .attr("transform", `translate(0,${this.height - this.marginBottom})`)
"transform",
"translate(0," + (this.height - this.marginBottom) + ")"
)
.call(d3.axisBottom(x).ticks(5)) .call(d3.axisBottom(x).ticks(5))
.append("text") .append("text")
.attr("x", this.width - 2) .attr("x", this.width - 2)
@@ -143,30 +127,30 @@ class HistogramBrush extends React.Component {
.attr("fill", "#000") .attr("fill", "#000")
.attr("text-anchor", "end") .attr("text-anchor", "end")
.attr("font-weight", "bold") .attr("font-weight", "bold")
.text(this.props.metadataField); .text(metadataField);
this.setState({ brush, xAxis }); this.setState({ brush, xAxis });
} }
} }
handleColorAction() { handleColorAction() {
this.props.dispatch({ const { dispatch, metadataField, initializeRanges } = this.props;
dispatch({
type: "color by continuous metadata", type: "color by continuous metadata",
colorAccessor: this.props.metadataField, colorAccessor: metadataField,
rangeMaxForColorAccessor: this.props.initializeRanges[ rangeMaxForColorAccessor: initializeRanges[metadataField].range.max
this.props.metadataField
].range.max
}); });
} }
render() { render() {
const { metadataField, ranges, colorAccessor } = this.props;
return ( return (
<div <div
style={{ style={{
marginTop: 10, marginTop: 10,
position: "flex" position: "flex"
}} }}
id={"histogram_" + this.props.metadataField} id={`histogram_${metadataField}`}
> >
<svg <svg
width={this.width} width={this.width}
@@ -175,9 +159,9 @@ class HistogramBrush extends React.Component {
this.drawHistogram(svgRef); this.drawHistogram(svgRef);
}} }}
> >
{this.props.ranges.min} {ranges.min}
{" to "} {" to "}
{this.props.ranges.max} {ranges.max}
</svg> </svg>
<span <span
onClick={this.handleColorAction.bind(this)} onClick={this.handleColorAction.bind(this)}
@@ -187,9 +171,7 @@ class HistogramBrush extends React.Component {
// padding: this.props.colorAccessor === this.props.metadataField ? 3 : "auto", // padding: this.props.colorAccessor === this.props.metadataField ? 3 : "auto",
borderRadius: 3, borderRadius: 3,
color: color:
this.props.colorAccessor === this.props.metadataField colorAccessor === metadataField ? globals.brightBlue : "black",
? globals.brightBlue
: "black",
// backgroundColor: this.props.colorAccessor === this.props.metadataField ? globals.brightBlue : "inherit", // backgroundColor: this.props.colorAccessor === this.props.metadataField ? globals.brightBlue : "inherit",
position: "relative", position: "relative",
top: -29, top: -29,
@@ -4,26 +4,28 @@
****************************************** ******************************************
******************************************/ ******************************************/
// jshint esversion: 6 // jshint esversion: 6
const setupParallelCoordinates = (width, height, margin) => { import * as d3 from "d3";
var container = d3.select("#parcoords");
var svg = container const setupParallelCoordinates = (width, height, margin) => {
const container = d3.select("#parcoords");
const svg = container
.append("svg") .append("svg")
.attr("width", width + margin.left + margin.right) .attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom) .attr("height", height + margin.top + margin.bottom)
.append("g") .append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); .attr("transform", `translate(${margin.left},${margin.top})`);
var canvas = container const canvas = container
.append("canvas") .append("canvas")
.attr("width", width * devicePixelRatio) .attr("width", width * devicePixelRatio)
.attr("height", height * devicePixelRatio) .attr("height", height * devicePixelRatio)
.style("width", width + "px") .style("width", `${width}px`)
.style("height", height + "px") .style("height", `${height}px`)
.style("margin-top", margin.top + "px") .style("margin-top", `${margin.top}px`)
.style("margin-left", margin.left + "px"); .style("margin-left", `${margin.left}px`);
var ctx = canvas.node().getContext("2d"); const ctx = canvas.node().getContext("2d");
ctx.globalCompositeOperation = "darken"; ctx.globalCompositeOperation = "darken";
ctx.globalAlpha = 0.15; ctx.globalAlpha = 0.15;
ctx.lineWidth = 1.5; ctx.lineWidth = 1.5;
+6 -12
View File
@@ -18,11 +18,10 @@ export const createDimensions = data => {
_.each(data, (value, key) => { _.each(data, (value, key) => {
if (value.range) { if (value.range) {
newArr.push({ newArr.push({
key: key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */, key /* room for confusion: lodash calls this key, it's also the name of the property parallel coords code is looking for */,
type: { type: {
within: (d, extent, dim) => { within: (d, extent, dim) =>
return extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1]; extent[0] <= dim.scale(d) && dim.scale(d) <= extent[1]
}
}, },
scale: d3 scale: d3
.scaleSqrt() .scaleSqrt()
@@ -41,18 +40,13 @@ export const brushstart = () => {
}; };
export const d3_functor = v => { export const d3_functor = v => {
return typeof v === "function" return typeof v === "function" ? v : () => v;
? v
: () => {
return v;
};
}; };
export const project = (d, dimensions, xscale) => { export const project = (d, dimensions, xscale) =>
return dimensions.map((p, i) => { dimensions.map((p, i) => {
// check if data element has property and contains a value // check if data element has property and contains a value
if (!(p.key in d) || d[p.key] === null) return null; if (!(p.key in d) || d[p.key] === null) return null;
return [xscale(i), p.scale(d[p.key])]; return [xscale(i), p.scale(d[p.key])];
}); });
};