diff --git a/client/configuration/eslint/eslint.js b/client/configuration/eslint/eslint.js index 4fcea456..1df6725b 100644 --- a/client/configuration/eslint/eslint.js +++ b/client/configuration/eslint/eslint.js @@ -32,6 +32,7 @@ module.exports = { "no-param-reassign": "off", "object-curly-newline": ["error", { consistent: true }], "react/prop-types": [0], - "space-before-function-paren": "off" + "space-before-function-paren": "off", + "function-paren-newline": "off" } }; diff --git a/client/src/components/continuous/drawLinesCanvas.js b/client/src/components/continuous/drawLinesCanvas.js deleted file mode 100644 index 04d69b62..00000000 --- a/client/src/components/continuous/drawLinesCanvas.js +++ /dev/null @@ -1,89 +0,0 @@ -// jshint esversion: 6 -import _ from "lodash"; -import { project } from "./util"; - -import renderQueue from "../../util/renderQueue"; - -/***************************************** -****************************************** - draw loop -****************************************** -******************************************/ - -const drawLinesCanvas = (ctx, dimensions, xscale) => d => { - ctx.globalAlpha = 0.1; - - if (d.__selected__) { - ctx.strokeStyle = d.__color__; - } 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; - } - - if (i === 0) { - ctx.moveTo(p[0], p[1]); - return; - } - - ctx.lineTo(p[0], p[1]); - }); - ctx.stroke(); -}; - -const drawCellLinesUsingRenderQueue = ( - metadata, - dimensions, - xscale, - ctx, - colorAccessor, - colorScale -) => { - const _renderLinesWithQueue = renderQueue( - drawLinesCanvas(ctx, dimensions, xscale, colorAccessor, colorScale) - ).rate(50); - _renderLinesWithQueue(metadata); - return _renderLinesWithQueue; -}; - -const drawCellLinesSync = ( - metadata, - dimensions, - xscale, - ctx, - colorAccessor, - colorScale -) => { - const _draw = drawLinesCanvas( - ctx, - dimensions, - xscale, - colorAccessor, - colorScale - ); - _.each(metadata, _draw); -}; - -export default drawCellLinesUsingRenderQueue; -// export default drawCellLinesUsingRenderQueue; diff --git a/client/src/components/graph/graph.js b/client/src/components/graph/graph.js index 679a7274..59cbac2e 100644 --- a/client/src/components/graph/graph.js +++ b/client/src/components/graph/graph.js @@ -14,7 +14,7 @@ import setupSVGandBrushElements from "./setupSVGandBrush"; import actions from "../../actions"; import _camera from "../../util/camera"; import _drawPoints from "./drawPointsRegl"; -import { scaleLinear } from "../../util/scaleLinear"; +import scaleLinear from "../../util/scaleLinear"; /* https://bl.ocks.org/mbostock/9078690 - quadtree for onClick / hover selections */ diff --git a/client/src/components/scatterplot/scatterplot.js b/client/src/components/scatterplot/scatterplot.js index 2e15f076..3b381fe2 100644 --- a/client/src/components/scatterplot/scatterplot.js +++ b/client/src/components/scatterplot/scatterplot.js @@ -14,7 +14,7 @@ import setupScatterplot from "./setupScatterplot"; import styles from "./scatterplot.css"; import _drawPoints from "./drawPointsRegl"; -import { scaleLinear } from "../../util/scaleLinear"; +import scaleLinear from "../../util/scaleLinear"; import { margin, width, height } from "./util"; import { kvCache } from "../../util/stateManager"; diff --git a/client/src/globals.js b/client/src/globals.js index 36e794ff..452a06f1 100644 --- a/client/src/globals.js +++ b/client/src/globals.js @@ -47,7 +47,7 @@ export const tiniestFontSize = 12; export const bolder = 700; -export let API = { +let _API = { // prefix: "http://api.clustering.czi.technology/api/", // prefix: "http://tabulamuris.cxg.czi.technology/api/", // prefix: "http://api-staging.clustering.czi.technology/api/", @@ -55,15 +55,14 @@ export let API = { version: "v0.2/" }; -if (window.CELLXGENE && window.CELLXGENE.API) API = window.CELLXGENE.API; +if (window.CELLXGENE && window.CELLXGENE.API) _API = window.CELLXGENE.API; +export const API = _API; export const accentFont = "Georgia,Times,Times New Roman,serif"; export const maxParagraphWidth = 600; export const maxControlsWidth = 800; export const graphMargin = { top: 20, right: 10, bottom: 30, left: 40 }; -// export const graphWidth = 1440 /* window width */ - 410 /* sidebar */ - (15 + 15) /* left right padding */ /* but responsive */; -// export const graphHeight = 500; export const graphWidth = 700; export const graphHeight = 700; diff --git a/client/src/middleware/updateCellColors.js b/client/src/middleware/updateCellColors.js index 5d11377c..64eaf4a1 100644 --- a/client/src/middleware/updateCellColors.js +++ b/client/src/middleware/updateCellColors.js @@ -3,7 +3,7 @@ import _ from "lodash"; import * as d3 from "d3"; import { interpolateViridis } from "d3-scale-chromatic"; import * as globals from "../globals"; -import { parseRGB } from "../util/parseRGB"; +import parseRGB from "../util/parseRGB"; /* https://medium.com/@jacobp100/you-arent-using-redux-middleware-enough-94ffe991e6 diff --git a/client/src/reducers/controls.js b/client/src/reducers/controls.js index b71e0d62..3846b10b 100644 --- a/client/src/reducers/controls.js +++ b/client/src/reducers/controls.js @@ -2,7 +2,7 @@ import _ from "lodash"; import { World, kvCache } from "../util/stateManager"; -import { parseRGB } from "../util/parseRGB"; +import parseRGB from "../util/parseRGB"; import Crossfilter from "../util/typedCrossfilter"; import * as globals from "../globals"; diff --git a/client/src/util/camera.js b/client/src/util/camera.js index 8820d803..95a69eac 100644 --- a/client/src/util/camera.js +++ b/client/src/util/camera.js @@ -1,9 +1,9 @@ // jshint esversion: 6 -var createCamera = require("orbit-camera"); -var createScroll = require("scroll-speed"); -var mp = require("mouse-position"); -var mb = require("mouse-pressed"); -var key = require("key-pressed"); +const createCamera = require("orbit-camera"); +const createScroll = require("scroll-speed"); +const mp = require("mouse-position"); +const mb = require("mouse-pressed"); +const key = require("key-pressed"); const panSpeed = 0.4; const scaleSpeed = 0.5; @@ -17,20 +17,19 @@ function attachCamera(canvas, opts) { opts.scale = opts.scale !== false; opts.rotate = opts.rotate !== false; - var scroll = createScroll(canvas, opts.scale); - var mbut = mb(canvas, opts.rotate); - var mpos = mp(canvas); - var camera = createCamera([0, 0, 1], [0, 0, -1], [0, 1, 0]); + const scroll = createScroll(canvas, opts.scale); + const mbut = mb(canvas, opts.rotate); + const mpos = mp(canvas); + const camera = createCamera([0, 0, 1], [0, 0, -1], [0, 1, 0]); camera.tick = tick; return camera; function tick() { - var ctrl = key("") || key(""); - var alt = key(""); - var height = canvas.height; - var width = canvas.width; + const ctrl = key("") || key(""); + const alt = key(""); + const { height, width } = canvas; if (opts.rotate && mbut.left && ctrl && !alt) { camera.rotate( @@ -41,23 +40,17 @@ function attachCamera(canvas, opts) { if ((opts.pan && mbut.right) || (mbut.left && !ctrl && !alt)) { camera.pan([ - panSpeed * - (mpos[0] - mpos.prev[0]) / - width * - Math.pow(camera.distance, 1), - panSpeed * - (mpos[1] - mpos.prev[1]) / - height * - Math.pow(camera.distance, 1) + ((panSpeed * (mpos[0] - mpos.prev[0])) / width) * camera.distance, + ((panSpeed * (mpos[1] - mpos.prev[1])) / height) * camera.distance ]); } if (opts.scale && scroll[1]) { - camera.distance *= Math.exp(scroll[1] * scaleSpeed / height); + camera.distance *= Math.exp((scroll[1] * scaleSpeed) / height); } if (opts.scale && (mbut.middle || (mbut.left && !ctrl && alt))) { - var d = mpos.y - mpos.prevY; + const d = mpos.y - mpos.prevY; if (!d) return; camera.distance *= Math.exp(d / height); diff --git a/client/src/util/parseRGB.js b/client/src/util/parseRGB.js index 7033aa50..2c6b4997 100644 --- a/client/src/util/parseRGB.js +++ b/client/src/util/parseRGB.js @@ -1,28 +1,27 @@ // jshint esversion: 6 -import { scaleRGB } from "./scaleRGB"; +import scaleRGB from "./scaleRGB"; // maintain a cache of already parsed RGB names, as it is reasonably expensive // to do this operation. This lets us have speed, but keep the pleasant ability // to talk about colors by their text description eg, 'rgb(0,0,1)' // -const colorCache = new Object(null); // no prototype +const colorCache = {}; function parseColorName(c) { if (c[0] !== "#") { const _c = c.replace(/[^\d,.]/g, "").split(","); return [scaleRGB(+_c[0]), scaleRGB(+_c[1]), scaleRGB(+_c[2])]; - } else { - var parsedHex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c); - return [ - scaleRGB(parseInt(parsedHex[1], 16)), - scaleRGB(parseInt(parsedHex[2], 16)), - scaleRGB(parseInt(parsedHex[3], 16)) - ]; } + const parsedHex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(c); + return [ + scaleRGB(parseInt(parsedHex[1], 16)), + scaleRGB(parseInt(parsedHex[2], 16)), + scaleRGB(parseInt(parsedHex[3], 16)) + ]; } -export const parseRGB = c => { - var cv = colorCache[c]; +export default c => { + let cv = colorCache[c]; if (!cv) { cv = parseColorName(c); colorCache[c] = cv; diff --git a/client/src/util/renderQueue.js b/client/src/util/renderQueue.js deleted file mode 100644 index be5d6d97..00000000 --- a/client/src/util/renderQueue.js +++ /dev/null @@ -1,82 +0,0 @@ -// jshint esversion: 6 -/***************************************** -****************************************** -Render Queue via http://bl.ocks.org/syntagmatic/raw/3341641/render-queue.js -****************************************** -******************************************/ - -const renderQueue = function(callback1234) { - var _queue = [], // data to be rendered - _rate = 300, // number of calls per frame - _invalidate = function() {}, // invalidate last render queue - _clear = function() {}; // clearing function - - var rq = function(ARRAY_FROM_CELLXGENE) { - if (ARRAY_FROM_CELLXGENE) rq.data(ARRAY_FROM_CELLXGENE); - _invalidate(); - _clear(); - rq.render(); - }; - - rq.render = function() { - var valid = true; - _invalidate = rq.invalidate = function() { - valid = false; - }; - - function doFrame() { - if (!valid) return true; - var chunk = _queue.splice(0, _rate); - chunk.map(callback1234); - timer_frame(doFrame); - } - - doFrame(); - }; - - rq.data = function(ARRAY_FROM_CELLXGENE) { - _invalidate(); - _queue = ARRAY_FROM_CELLXGENE.slice(0); // creates a copy of the data - return rq; - }; - - rq.add = function(data) { - _queue = _queue.concat(data); - }; - - rq.rate = function(value) { - if (!arguments.length) return _rate; - _rate = value; - return rq; - }; - - rq.remaining = function() { - return _queue.length; - }; - - // clear the canvas - rq.clear = function(func) { - if (!arguments.length) { - _clear(); - return rq; - } - _clear = func; - return rq; - }; - - rq.invalidate = _invalidate; - - var timer_frame = - window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function(callback) { - setTimeout(callback, 17); - }; - - return rq; -}; - -export default renderQueue; diff --git a/client/src/util/scaleLinear.js b/client/src/util/scaleLinear.js index a675011d..554938b6 100644 --- a/client/src/util/scaleLinear.js +++ b/client/src/util/scaleLinear.js @@ -8,11 +8,9 @@ // myScale(0) === -1 // this is is equivalent to d3.scaleLinear().domain([0,1]).range([-1,1]) -export const scaleLinear = (domain, range) => { +export default (domain, range) => { const domainStart = domain[0]; const scale = (range[1] - range[0]) / (domain[1] - domain[0]); const rangeStart = range[0]; - return function(value) { - return (value - domainStart) * scale + rangeStart; - }; + return value => (value - domainStart) * scale + rangeStart; }; diff --git a/client/src/util/scaleRGB.js b/client/src/util/scaleRGB.js index f4995667..b705e201 100644 --- a/client/src/util/scaleRGB.js +++ b/client/src/util/scaleRGB.js @@ -1,5 +1,5 @@ // jshint esversion: 6 -export const scaleRGB = input => { +export default input => { const outputMax = 1; const outputMin = 0; diff --git a/client/src/util/schema.js b/client/src/util/schema.js deleted file mode 100644 index 6d6161d1..00000000 --- a/client/src/util/schema.js +++ /dev/null @@ -1,41 +0,0 @@ -// jshint esversion: 6 - -// In the case where the REST server does not implement data schema -// declaration, we attempt to deduce it by sniffing the data. -// -export function createSchemaByDataSniffing(ranges) { - let schema = {}; - _.forEach(ranges, (value, key) => { - schema[key] = { - displayname: key, - variabletype: value.options ? "categorical" : "continuous" - }; - - // Metadata field type is inferred by sniffing the data. This has some risks. - // Caveats: - // * Values have been converted to native JS objects by the JSON parser. - // * Lots of assumptions about he REST API behaving properly (eg, min/max - // are the same type, etc). - let type; - if (schema[key].variabletype === "continuous" && value.range) { - // Use min/max as a proxy for all data. - const min = value.range.min; - const max = value.range.max; - type = - typeof min !== "number" || typeof max !== "number" - ? "string" - : Number.isSafeInteger(min) && Number.isSafeInteger(max) - ? "int" - : "float"; - } else { - // use an option value as a proxy for all data - const aVal = value.options[0]; - type = - typeof aVal !== "number" - ? "string" - : Number.isSafeInteger(aVal) ? "int" : "float"; - } - schema[key].type = type; - }); - return schema; -} diff --git a/client/src/util/typedCrossfilter/positiveIntervals.js b/client/src/util/typedCrossfilter/positiveIntervals.js index 1578812f..1f255fea 100644 --- a/client/src/util/typedCrossfilter/positiveIntervals.js +++ b/client/src/util/typedCrossfilter/positiveIntervals.js @@ -83,7 +83,7 @@ class PositiveIntervals { if (i === points.length - 1 || p[0] !== points[i + 1][0]) { if (aDepth === 1 && depth === 1) { - intervalStart = p[0]; + [intervalStart] = p; } else if (intervalStart !== undefined) { res.push([intervalStart, p[0]]); intervalStart = undefined; @@ -113,7 +113,7 @@ class PositiveIntervals { const p = points[i]; depth += p[2] ? 1 : -1; if (depth === 2) { - intervalStart = p[0]; + [intervalStart] = p; } else if (intervalStart !== undefined) { res.push([intervalStart, p[0]]); intervalStart = undefined;