From df671192be84e675e5d10928cdca453e5038dc90 Mon Sep 17 00:00:00 2001
From: Colin Megill
Date: Mon, 22 Oct 2018 15:46:37 -0400
Subject: [PATCH] Begin integrating blueprint (#359)
* toast test
* modify webpack build to allow for global CSS; use CSS modules to scope component styling
* remove heatmap
* add label to index resets
* swapping out buttons for blueprint
* adding constants to globals
* swapping out blueprint buttons
* title position, sidebar improvements
* sidebar styles
* adding toasts for validation errors
* zebra section trial
* integrating blueprint, switching buttons over, breaking out scatter
* clean up console
---
.../webpack/webpack.config.dev.js | 21 +-
.../webpack/webpack.config.prod.js | 38 ++-
client/index.html | 4 +-
client/index_template.html | 15 +-
client/package-lock.json | 271 +++++++++++++++---
client/package.json | 4 +
.../components/brushableHistogram/index.js | 12 +-
.../src/components/categorical/categorical.js | 14 +-
client/src/components/categorical/category.js | 83 +++---
client/src/components/categorical/value.js | 57 ++--
.../src/components/continuous/continuous.js | 17 +-
.../continuous/parallelCoordinates.css | 40 +--
.../src/components/continuousLegend/index.js | 16 +-
.../components/expression/cellSetButtons.js | 71 -----
.../components/expression/diffExpHeatmap.js | 83 ------
.../src/components/expression/expression.css | 0
.../src/components/expression/heatmapRow.js | 154 ----------
.../components/expression/heatmapSquare.js | 30 --
client/src/components/framework/buttons.css | 2 +-
client/src/components/framework/container.css | 2 +-
client/src/components/framework/toasters.js | 12 +
.../geneExpression/cellSetButtons.js | 46 +++
.../expressionButtons.js | 53 +---
client/src/components/geneExpression/index.js | 167 ++++++-----
client/src/components/graph/graph.css | 8 +-
client/src/components/graph/graph.js | 81 ++----
client/src/components/leftsidebar.js | 47 ++-
.../components/scatterplot/scatterplot.css | 9 +-
.../src/components/scatterplot/scatterplot.js | 41 ++-
client/src/components/scatterplot/util.js | 2 +-
client/src/globals.js | 37 ++-
client/src/index.css | 9 +
client/src/index.js | 2 +
client/src/reducers/controls.js | 6 +
34 files changed, 717 insertions(+), 737 deletions(-)
delete mode 100644 client/src/components/expression/cellSetButtons.js
delete mode 100644 client/src/components/expression/diffExpHeatmap.js
delete mode 100644 client/src/components/expression/expression.css
delete mode 100644 client/src/components/expression/heatmapRow.js
delete mode 100644 client/src/components/expression/heatmapSquare.js
create mode 100644 client/src/components/framework/toasters.js
create mode 100644 client/src/components/geneExpression/cellSetButtons.js
rename client/src/components/{expression => geneExpression}/expressionButtons.js (58%)
diff --git a/client/configuration/webpack/webpack.config.dev.js b/client/configuration/webpack/webpack.config.dev.js
index 76f9ae6a..3b273a11 100644
--- a/client/configuration/webpack/webpack.config.dev.js
+++ b/client/configuration/webpack/webpack.config.dev.js
@@ -6,6 +6,8 @@ const HtmlWebpackPlugin = require("html-webpack-plugin");
const src = path.resolve("src");
const nodeModules = path.resolve("node_modules");
+const babelOptions = require("../babel/babel.dev");
+
module.exports = {
mode: "development",
devtool: "eval",
@@ -22,11 +24,12 @@ module.exports = {
test: /\.js$/,
include: src,
loader: "babel-loader",
- options: require("../babel/babel.dev")
+ options: babelOptions
},
{
test: /\.css$/,
- include: [src, nodeModules],
+ include: src,
+ exclude: [path.resolve(src, "index.css")],
loader: [
{
loader: "style-loader"
@@ -35,12 +38,24 @@ module.exports = {
loader: "css-loader",
options: {
modules: true,
- importLoaders: 1,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
}
]
},
+ {
+ test: /index\.css$/,
+ include: [path.resolve(src, "index.css")],
+ loader: [
+ {
+ loader: "style-loader"
+ },
+ {
+ loader: "css-loader"
+ }
+ ]
+ },
+
{ test: /\.json$/, include: [src, nodeModules], loader: "json-loader" },
{
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
diff --git a/client/configuration/webpack/webpack.config.prod.js b/client/configuration/webpack/webpack.config.prod.js
index bd60898b..6cffc8b4 100644
--- a/client/configuration/webpack/webpack.config.prod.js
+++ b/client/configuration/webpack/webpack.config.prod.js
@@ -1,6 +1,5 @@
// jshint esversion: 6
const path = require("path");
-const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const SWPrecacheWebpackPlugin = require("sw-precache-webpack-plugin");
@@ -9,6 +8,8 @@ const HtmlWebpackInlineSourcePlugin = require("html-webpack-inline-source-plugin
const src = path.resolve("src");
const nodeModules = path.resolve("node_modules");
+const babelOptions = require("../babel/babel.prod");
+
const publicPath = "/";
module.exports = {
@@ -16,7 +17,7 @@ module.exports = {
bail: true,
cache: false,
devtool: "cheap-source-map",
- entry: ["./src/index"],
+ entry: ["./src/index.js"],
output: {
path: path.resolve("build"),
filename: "static/js/[name].[chunkhash:8].js",
@@ -28,15 +29,14 @@ module.exports = {
test: /\.js$/,
include: src,
loader: "babel-loader",
- options: require("../babel/babel.prod")
+ options: babelOptions
},
{
test: /\.css$/,
- include: [src, nodeModules],
- loader: [
- {
- loader: MiniCssExtractPlugin.loader
- },
+ include: src,
+ exclude: [path.resolve(src, "index.css")],
+ use: [
+ MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
@@ -47,6 +47,19 @@ module.exports = {
}
]
},
+ {
+ test: /index\.css$/,
+ include: [path.resolve(src, "index.css")],
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
+ loader: "css-loader",
+ options: {
+ importLoaders: 1
+ }
+ }
+ ]
+ },
{
test: /\.json$/,
include: [src, nodeModules],
@@ -57,7 +70,10 @@ module.exports = {
test: /\.(jpg|png|gif|eot|svg|ttf|woff|woff2)(\?.*)?$/,
include: [src, nodeModules],
loader: "file-loader",
- query: { name: "static/media/[name].[hash:8].[ext]" }
+ options: {
+ name: "[name].[hash:8].[ext]",
+ outputPath: "static/media/"
+ }
},
{
test: /\.(mp4|webm)(\?.*)?$/,
@@ -97,7 +113,7 @@ module.exports = {
})
],
performance: {
- maxEntrypointSize: 750000,
- maxAssetSize: 750000
+ maxEntrypointSize: 2000000,
+ maxAssetSize: 2000000
}
};
diff --git a/client/index.html b/client/index.html
index b0eefdd0..08259783 100644
--- a/client/index.html
+++ b/client/index.html
@@ -6,9 +6,9 @@
cellxgene
diff --git a/client/package-lock.json b/client/package-lock.json
index 6f9ce9e3..583d159d 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -913,6 +913,47 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@blueprintjs/core": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/core/-/core-3.7.0.tgz",
+ "integrity": "sha512-fr1jgAY/sPWJ7BorebuyLQKTTk7x+/1suayaxKVh1WMQ7aIi3Zb7HnJPEVFQyaT+9rVl97b7/2DiID3N8/UGMw==",
+ "requires": {
+ "@blueprintjs/icons": "^3.2.0",
+ "@types/dom4": "^2.0.0",
+ "classnames": "^2.2",
+ "dom4": "^2.0.1",
+ "normalize.css": "^8.0.0",
+ "popper.js": "^1.14.1",
+ "react-popper": "^1.0.0",
+ "react-transition-group": "^2.2.1",
+ "resize-observer-polyfill": "^1.5.0",
+ "tslib": "^1.9.0"
+ }
+ },
+ "@blueprintjs/icons": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.2.0.tgz",
+ "integrity": "sha512-MoI4TdZ2QMM9DEd+/vJOMSlhuvPID3Zip0TB/MB1J7p7GnUThIRq2FlETMUg6ig1GZweAWNl7cUtYFNHZ3EiUQ==",
+ "requires": {
+ "classnames": "^2.2",
+ "tslib": "^1.9.0"
+ }
+ },
+ "@blueprintjs/select": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@blueprintjs/select/-/select-3.2.0.tgz",
+ "integrity": "sha512-kieg23ktzCXBUT7oVKBwlnPrjpwH8GgB722BL4nMV+c9cnt9gHuhk6eGORd3w8tK9gI85F/+brVkimbmQShVZg==",
+ "requires": {
+ "@blueprintjs/core": "^3.6.0",
+ "classnames": "^2.2",
+ "tslib": "^1.9.0"
+ }
+ },
+ "@types/dom4": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/dom4/-/dom4-2.0.1.tgz",
+ "integrity": "sha512-kSkVAvWmMZiCYtvqjqQEwOmvKwcH+V4uiv3qPQ8pAh1Xl39xggGEo8gHUqV4waYGHezdFw0rKBR8Jt0CrQSDZA=="
+ },
"@webassemblyjs/ast": {
"version": "1.7.8",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.8.tgz",
@@ -1632,6 +1673,11 @@
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
"dev": true
},
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -2054,7 +2100,7 @@
},
"babel-plugin-syntax-object-rest-spread": {
"version": "6.13.0",
- "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
"dev": true
},
@@ -2167,7 +2213,6 @@
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
- "dev": true,
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
@@ -2176,8 +2221,7 @@
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
- "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
- "dev": true
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
}
}
},
@@ -2489,7 +2533,7 @@
},
"browserify-aes": {
"version": "1.2.0",
- "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"dev": true,
"requires": {
@@ -2526,7 +2570,7 @@
},
"browserify-rsa": {
"version": "4.0.1",
- "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"dev": true,
"requires": {
@@ -2580,7 +2624,7 @@
},
"buffer": {
"version": "4.9.1",
- "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"dev": true,
"requires": {
@@ -2951,6 +2995,11 @@
}
}
},
+ "classnames": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
+ "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+ },
"clean-css": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
@@ -3228,8 +3277,7 @@
"core-js": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
- "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==",
- "dev": true
+ "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
},
"core-util-is": {
"version": "1.0.2",
@@ -3258,7 +3306,7 @@
},
"create-hash": {
"version": "1.2.0",
- "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"dev": true,
"requires": {
@@ -3271,7 +3319,7 @@
},
"create-hmac": {
"version": "1.1.7",
- "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"dev": true,
"requires": {
@@ -3283,6 +3331,15 @@
"sha.js": "^2.4.8"
}
},
+ "create-react-context": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.3.tgz",
+ "integrity": "sha512-CQBmD0+QGgTaxDL3OX1IDXYqjkp2It4RIbcb99jS6AEg27Ga+a9G3JtK6SIu0HBwPLZlmwt9F7UwWA4Bn92Rag==",
+ "requires": {
+ "fbjs": "^0.8.0",
+ "gud": "^1.0.0"
+ }
+ },
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -3945,7 +4002,7 @@
},
"diffie-hellman": {
"version": "5.0.3",
- "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"dev": true,
"requires": {
@@ -3993,6 +4050,11 @@
"utila": "~0.4"
}
},
+ "dom-helpers": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz",
+ "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg=="
+ },
"dom-scroll-into-view": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.0.1.tgz",
@@ -4025,6 +4087,11 @@
"urijs": "^1.16.1"
}
},
+ "dom4": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/dom4/-/dom4-2.1.3.tgz",
+ "integrity": "sha512-begvh4z5GV0kyxx+YgJZ7sIo/jsELx/v7MQxoLZpOvT5yFo18X8dfgtUmKAwdGuyMeugncylarLHlO4gIK6YNw=="
+ },
"domain-browser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
@@ -4152,6 +4219,14 @@
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
"dev": true
},
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
@@ -4539,7 +4614,7 @@
},
"load-json-file": {
"version": "2.0.0",
- "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true,
"requires": {
@@ -4716,7 +4791,7 @@
},
"events": {
"version": "1.1.1",
- "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
},
"evp_bytestokey": {
@@ -4950,6 +5025,27 @@
"bser": "^2.0.0"
}
},
+ "fbjs": {
+ "version": "0.8.17",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
+ "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
+ "requires": {
+ "core-js": "^1.0.0",
+ "isomorphic-fetch": "^2.1.1",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^0.7.18"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ }
+ }
+ },
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
@@ -5010,7 +5106,7 @@
},
"finalhandler": {
"version": "1.1.1",
- "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"dev": true,
"requires": {
@@ -5734,7 +5830,7 @@
},
"get-stream": {
"version": "3.0.0",
- "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true
},
@@ -5862,6 +5958,11 @@
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
"dev": true
},
+ "gud": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz",
+ "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw=="
+ },
"handlebars": {
"version": "4.0.12",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz",
@@ -6113,7 +6214,7 @@
},
"html-webpack-plugin": {
"version": "3.2.0",
- "resolved": "http://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
"integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
"dev": true,
"requires": {
@@ -6189,7 +6290,7 @@
},
"http-errors": {
"version": "1.6.3",
- "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"dev": true,
"requires": {
@@ -6412,7 +6513,7 @@
},
"is-builtin-module": {
"version": "1.0.0",
- "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"dev": true,
"requires": {
@@ -6645,8 +6746,7 @@
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
- "dev": true
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-symbol": {
"version": "1.0.2",
@@ -6696,6 +6796,15 @@
"isarray": "1.0.0"
}
},
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ }
+ },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -7411,7 +7520,7 @@
},
"json5": {
"version": "0.5.1",
- "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true
},
@@ -7501,7 +7610,7 @@
},
"load-json-file": {
"version": "1.1.0",
- "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
"requires": {
@@ -7830,7 +7939,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
- "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
}
@@ -7955,7 +8064,7 @@
},
"minimist": {
"version": "0.0.8",
- "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
},
@@ -8000,7 +8109,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
@@ -8128,6 +8237,15 @@
"lower-case": "^1.1.1"
}
},
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ },
"node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -8221,6 +8339,11 @@
"remove-trailing-separator": "^1.0.1"
}
},
+ "normalize.css": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.0.tgz",
+ "integrity": "sha512-iXcbM3NWr0XkNyfiSBsoPezi+0V92P9nj84yVV1/UZxRUrGczgX/X91KMAGM0omWLY2+2Q1gKD/XRn4gQRDB2A=="
+ },
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -9712,7 +9835,7 @@
},
"parse-asn1": {
"version": "5.1.1",
- "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
"integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
"dev": true,
"requires": {
@@ -9899,6 +10022,11 @@
"integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
"dev": true
},
+ "popper.js": {
+ "version": "1.14.4",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.4.tgz",
+ "integrity": "sha1-juwdj/AqWjoVLdQ0FKFce3n9abY="
+ },
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -10045,6 +10173,14 @@
"integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
"dev": true
},
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
"promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@@ -10306,9 +10442,27 @@
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.2.0.tgz",
"integrity": "sha512-ZWqIiOr5wTqtE6NNM9JgWBgNbq2JRi79rmqf2j50V1ewC6LiwKFhq7J/AjaVKBi5oPE4/9JN/jMKaVrJlIQoiw=="
},
+ "react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "react-popper": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.0.2.tgz",
+ "integrity": "sha512-vjZ94ki8sfCAg45MMi4uqnUUWdzbnYkb95sR2+HgiMaAPzQcy4DfDKYtYUOhhE+sdtkufWcUHLv09DmH2Js57w==",
+ "requires": {
+ "babel-runtime": "6.x.x",
+ "create-react-context": "^0.2.1",
+ "popper.js": "^1.14.1",
+ "prop-types": "^15.6.1",
+ "typed-styles": "^0.0.5",
+ "warning": "^3.0.0"
+ }
+ },
"react-redux": {
"version": "5.0.7",
- "resolved": "http://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
"integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==",
"requires": {
"hoist-non-react-statics": "^2.5.0",
@@ -10328,6 +10482,17 @@
"shallowequal": "^1.0.1"
}
},
+ "react-transition-group": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.0.tgz",
+ "integrity": "sha512-qYB3JBF+9Y4sE4/Mg/9O6WFpdoYjeeYqx0AFb64PTazVy8RPMiE3A47CG9QmM4WJ/mzDiZYslV+Uly6O1Erlgw==",
+ "requires": {
+ "dom-helpers": "^3.3.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -10372,7 +10537,7 @@
},
"readable-stream": {
"version": "2.3.6",
- "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true,
"requires": {
@@ -10957,6 +11122,11 @@
"resolve-from": "^1.0.0"
}
},
+ "resize-observer-polyfill": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz",
+ "integrity": "sha512-M2AelyJDVR/oLnToJLtuDJRBBWUGUvvGigj1411hXhAdyFWqMaqHp7TixW3FpiLuVaikIcR1QL+zqoJoZlOgpg=="
+ },
"resolve": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
@@ -11390,7 +11560,7 @@
},
"minimist": {
"version": "1.2.0",
- "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
},
@@ -11566,8 +11736,7 @@
"setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
- "dev": true
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
},
"setprototypeof": {
"version": "1.1.0",
@@ -11577,7 +11746,7 @@
},
"sha.js": {
"version": "2.4.11",
- "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"dev": true,
"requires": {
@@ -12031,7 +12200,7 @@
},
"strip-ansi": {
"version": "3.0.1",
- "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
@@ -12267,7 +12436,7 @@
},
"through": {
"version": "2.3.8",
- "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
@@ -12413,8 +12582,7 @@
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
- "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
- "dev": true
+ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
},
"tty-browserify": {
"version": "0.0.0",
@@ -12456,12 +12624,22 @@
"mime-types": "~2.1.18"
}
},
+ "typed-styles": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.5.tgz",
+ "integrity": "sha512-ht+rEe5UsdEBAa3gr64+QjUOqjOLJfWLvl5HZR5Ev9uo/OnD3p43wPeFSB1hNFc13GXQF/JU1Bn0YHLUqBRIlw=="
+ },
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
+ "ua-parser-js": {
+ "version": "0.7.18",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz",
+ "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA=="
+ },
"uglify-js": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
@@ -12894,6 +13072,14 @@
"makeerror": "1.0.x"
}
},
+ "warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
+ "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
"watch": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz",
@@ -12906,7 +13092,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
- "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
}
@@ -13501,6 +13687,11 @@
"iconv-lite": "0.4.24"
}
},
+ "whatwg-fetch": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
+ "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
+ },
"whatwg-mimetype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz",
@@ -13564,7 +13755,7 @@
},
"wrap-ansi": {
"version": "2.1.0",
- "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"dev": true,
"requires": {
@@ -13672,7 +13863,7 @@
},
"yargs": {
"version": "11.1.0",
- "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
"integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
"dev": true,
"requires": {
diff --git a/client/package.json b/client/package.json
index 2a2e363c..456fc5c9 100644
--- a/client/package.json
+++ b/client/package.json
@@ -27,6 +27,9 @@
"eslint-scope": "3.7.1"
},
"dependencies": {
+ "@blueprintjs/core": "^3.7.0",
+ "@blueprintjs/icons": "^3.2.0",
+ "@blueprintjs/select": "^3.2.0",
"canvas-fit": "^1.5.0",
"d3": "^4.10.0",
"d3-scale-chromatic": "^1.3.0",
@@ -38,6 +41,7 @@
"memoize-one": "^4.0.0",
"mouse-position": "^2.0.1",
"mouse-pressed": "^1.0.0",
+ "normalize.css": "^8.0.0",
"orbit-camera": "^1.0.0",
"query-string": "^6.1.0",
"react": "^16.4.2",
diff --git a/client/src/components/brushableHistogram/index.js b/client/src/components/brushableHistogram/index.js
index 8dc06062..d9401bdc 100644
--- a/client/src/components/brushableHistogram/index.js
+++ b/client/src/components/brushableHistogram/index.js
@@ -230,9 +230,9 @@ class HistogramBrush extends React.Component {
colorAccessor,
isUserDefined,
isDiffExp,
- diffExp_avgDiff,
- diffExp_set1AvgExp,
- diffExp_set2AvgExp,
+ avgDiff,
+ set1AvgExp,
+ set2AvgExp,
scatterplotXXaccessor,
scatterplotYYaccessor
} = this.props;
@@ -269,7 +269,7 @@ class HistogramBrush extends React.Component {
}}
>
1:
- {` ${diffExp_set1AvgExp.toPrecision(2)}`}
+ {` ${set1AvgExp.toPrecision(2)}`}
2:
- {` ${diffExp_set2AvgExp.toPrecision(2)}`}
+ {` ${set2AvgExp.toPrecision(2)}`}
- {`Av. Diff: ${diffExp_avgDiff.toFixed(2)}`}
+ {`Av. Diff: ${avgDiff.toFixed(2)}`}
- Categorical Metadata
+
+ Categorical Metadata
+
{_.map(ranges, (value, key) => {
const isColorField = key.includes("color") || key.includes("Color");
const isSelectableCategory =
diff --git a/client/src/components/categorical/category.js b/client/src/components/categorical/category.js
index 13206e27..976041de 100644
--- a/client/src/components/categorical/category.js
+++ b/client/src/components/categorical/category.js
@@ -119,34 +119,11 @@ class Category extends React.Component {
-
- {
- this.setState({ isExpanded: !isExpanded });
- }}
- >
- {isExpanded ? : }
-
- {metadataField}
+
{
@@ -156,29 +133,41 @@ class Category extends React.Component {
checked={isChecked}
type="checkbox"
/>
-
-
-
-
+
+ {""}
+
+
+
{
+ this.setState({ isExpanded: !isExpanded });
+ }}
+ >
+ {metadataField}
+ {isExpanded ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
- {isExpanded ? this.renderCategoryItems() : null}
+ {isExpanded ? this.renderCategoryItems() : null}
+
+ {count}
+
- {value}
-
-
- {count}
-
+
);
}
diff --git a/client/src/components/continuous/continuous.js b/client/src/components/continuous/continuous.js
index 037a0aef..3749586b 100644
--- a/client/src/components/continuous/continuous.js
+++ b/client/src/components/continuous/continuous.js
@@ -4,6 +4,7 @@
import React from "react";
import _ from "lodash";
import { connect } from "react-redux";
+import * as globals from "../../globals";
import HistogramBrush from "../brushableHistogram";
@@ -48,8 +49,20 @@ class Continuous extends React.Component {
}
return (
-
- {this.hasContinuous ?
Continuous metadata
: null}
+
+ {this.hasContinuous ? (
+
+ Continuous metadata
+
+ ) : null}
{_.map(ranges, (value, key) => {
const isColorField = key.includes("color") || key.includes("Color");
if (value.range && key !== "name" && !isColorField) {
diff --git a/client/src/components/continuous/parallelCoordinates.css b/client/src/components/continuous/parallelCoordinates.css
index 8e3a4fa0..b2affc9c 100644
--- a/client/src/components/continuous/parallelCoordinates.css
+++ b/client/src/components/continuous/parallelCoordinates.css
@@ -7,24 +7,24 @@ body {
}
*/
-.parcoords {
+:local(.parcoords) {
display: block;
}
-.parcoords svg,
-.parcoords canvas {
+:local(.parcoords) svg,
+:local(.parcoords) canvas {
font: 10px sans-serif;
position: absolute;
}
-.parcoords canvas {
+:local(.parcoords) canvas {
opacity: 0.9;
pointer-events: none;
}
-.axis .title {
+:local(.axis .title) {
font-size: 10px;
- transform: rotate(-21deg) translate(-5px,-6px);
+ transform: rotate(-21deg) translate(-5px, -6px);
fill: #222;
cursor: pointer;
}
@@ -32,14 +32,14 @@ body {
/* -webkit-filter: grayscale(100%);
filter: grayscale(100%); */
-.axis line,
-.axis path {
+:local(.axis) line,
+:local(.axis) path {
fill: none;
stroke: #ccc;
stroke-width: 1px;
}
-.axis .tick text {
+:local(.axis .tick) text {
fill: #222;
pointer-events: none;
}
@@ -52,39 +52,39 @@ old, from reference bl.ocks
}
*/
-.axis:hover line,
-.axis:hover path,
-.axis.active line,
-.axis.active path {
+:local(.axis:hover) line,
+:local(.axis:hover) path,
+:local(.axis.active) line,
+:local(.axis.active) path {
fill: none;
stroke: #222;
stroke-width: 1px;
}
-.axis:hover .title {
+:local(.axis:hover .title) {
font-weight: bold;
}
-.axis:hover .tick text {
+:local(.axis:hover .tick) text {
opacity: 1;
}
-.axis.active .title {
+:local(.axis.active .title) {
font-weight: bold;
}
-.axis.active .tick text {
+:local(.axis.active .tick) text {
opacity: 1;
font-weight: bold;
}
-.brush .extent {
- fill-opacity: .3;
+:local(.brush .extent) {
+ fill-opacity: 0.3;
stroke: #fff;
stroke-width: 1px;
}
-.pre {
+:local(.pre) {
width: 100%;
height: 300px;
margin: 6px 12px;
diff --git a/client/src/components/continuousLegend/index.js b/client/src/components/continuousLegend/index.js
index 9fbf0969..68f0d384 100644
--- a/client/src/components/continuousLegend/index.js
+++ b/client/src/components/continuousLegend/index.js
@@ -6,7 +6,7 @@ import { interpolateViridis } from "d3-scale-chromatic";
// create continuous color legend
// http://bl.ocks.org/syntagmatic/e8ccca52559796be775553b467593a9f
-const continuous = (selectorId, colorscale) => {
+const continuous = (selectorId, colorscale, colorAccessor) => {
const legendheight = 200;
const legendwidth = 80;
const margin = { top: 10, right: 60, bottom: 10, left: 2 };
@@ -84,6 +84,17 @@ const continuous = (selectorId, colorscale) => {
`translate(${legendwidth - margin.left - margin.right + 3},${margin.top})`
)
.call(legendaxis);
+
+ // text label for the y axis
+ // svg
+ // .append("text")
+ // .attr("transform", "rotate(-90)")
+ // .attr("y", 3)
+ // .attr("x", 0 - legendheight / 2)
+ // .attr("dy", "1em")
+ // .style("text-anchor", "middle")
+ // .style("fill", "white")
+ // .text(colorAccessor);
};
@connect(state => ({
@@ -115,7 +126,8 @@ class ContinuousLegend extends React.Component {
if (colorScale.range()[0][0] !== "#") {
continuous(
"#continuous_legend",
- d3.scaleSequential(interpolateViridis).domain(colorScale.domain())
+ d3.scaleSequential(interpolateViridis).domain(colorScale.domain()),
+ colorAccessor
);
}
}
diff --git a/client/src/components/expression/cellSetButtons.js b/client/src/components/expression/cellSetButtons.js
deleted file mode 100644
index 24cd73e1..00000000
--- a/client/src/components/expression/cellSetButtons.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// jshint esversion: 6
-import React from "react";
-import _ from "lodash";
-import { connect } from "react-redux";
-import * as globals from "../../globals";
-
-@connect()
-class CellSetButton extends React.Component {
- set() {
- const {
- differential,
- crossfilter,
- dispatch,
- eitherCellSetOneOrTwo
- } = this.props;
-
- const set = _.map(crossfilter.allFiltered(), "name");
-
- if (!differential.diffExp) {
- /* diffexp needs to be cleared before we store a new set */
- dispatch({
- type: `store current cell selection as differential set ${eitherCellSetOneOrTwo}`,
- data: set
- });
- }
- }
-
- render() {
- const { differential, eitherCellSetOneOrTwo } = this.props;
- const cellListName = `celllist${eitherCellSetOneOrTwo}`;
- return (
-
-
-
- {" "}
- {eitherCellSetOneOrTwo}
- {": "}
-
-
- {differential[cellListName]
- ? `${differential[cellListName].length} cells`
- : "0 cells"}
-
-
-
- );
- }
-}
-
-export default CellSetButton;
diff --git a/client/src/components/expression/diffExpHeatmap.js b/client/src/components/expression/diffExpHeatmap.js
deleted file mode 100644
index 53810e66..00000000
--- a/client/src/components/expression/diffExpHeatmap.js
+++ /dev/null
@@ -1,83 +0,0 @@
-// jshint esversion: 6
-import React from "react";
-import _ from "lodash";
-import { connect } from "react-redux";
-import * as d3 from "d3";
-import { interpolateGreys } from "d3-scale-chromatic";
-import HeatmapRow from "./heatmapRow";
-
-/**********************************
-***********************************
-***********************************
- DiffExp Heatmap
-***********************************
-***********************************
-**********************************/
-
-@connect(state => ({
- differential: state.differential,
- world: state.controls.world
-}))
-class Heatmap extends React.Component {
- render() {
- const { world, differential } = this.props;
- if (!differential.diffExp) {
- return
Select cells & compute differential to see heatmap
;
- }
-
- // summarize the information for display.
- const topGenes = _.map(differential.diffExp, val => ({
- varIndex: val[0],
- geneName: world.varAnnotations[val[0]].name,
- avgDiff: val[1],
- set1AvgExp: val[4],
- set2AvgExp: val[5]
- }));
-
- // average expression extent
- const extent = d3.extent(
- _.concat(
- _.map(differential.diffExp, val => val[4]),
- _.map(differential.diffExp, val => val[5])
- )
- );
-
- const greyColorScale = d3
- .scaleSequential()
- .domain(extent)
- .interpolator(interpolateGreys);
-
- return (
-
-
-
Gene
-
1
-
2
-
ave diff
-
- {topGenes.map(g => {
- const { geneName, avgDiff, set1AvgExp, set2AvgExp } = g;
- return (
-
- );
- })}
-
- );
- }
-}
-
-export default Heatmap;
diff --git a/client/src/components/expression/expression.css b/client/src/components/expression/expression.css
deleted file mode 100644
index e69de29b..00000000
diff --git a/client/src/components/expression/heatmapRow.js b/client/src/components/expression/heatmapRow.js
deleted file mode 100644
index 5e41a6b4..00000000
--- a/client/src/components/expression/heatmapRow.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import React from "react";
-import { connect } from "react-redux";
-import { FaPaintBrush } from "react-icons/fa";
-import HeatmapSquare from "./heatmapSquare";
-import * as globals from "../../globals";
-import actions from "../../actions";
-
-/**********************************
-***********************************
-***********************************
- Row
-***********************************
-***********************************
-**********************************/
-@connect(state => ({
- scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
- scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
- colorAccessor: state.controls.colorAccessor
-}))
-class HeatmapRow extends React.Component {
- handleGeneColorScaleClick() {
- return () => {
- const { dispatch, gene } = this.props;
- dispatch(actions.requestSingleGeneExpressionCountsForColoringPOST(gene));
- };
- }
-
- handleSetGeneAsScatterplotX() {
- return () => {
- const { dispatch, gene } = this.props;
- dispatch({
- type: "set scatterplot x",
- data: gene
- });
- };
- }
-
- handleSetGeneAsScatterplotY() {
- return () => {
- const { dispatch, gene } = this.props;
- dispatch({
- type: "set scatterplot y",
- data: gene
- });
- };
- }
-
- render() {
- const {
- gene,
- aveDiff,
- set1exp,
- set2exp,
- greyColorScale,
- scatterplotXXaccessor,
- scatterplotYYaccessor,
- colorAccessor
- } = this.props;
- return (
-
-
-
- {gene}
-
-
-
-
-
- {aveDiff.toFixed(2)}
-
-
- X
-
-
- Y
-
-
-
-
-
- );
- }
-}
-
-export default HeatmapRow;
diff --git a/client/src/components/expression/heatmapSquare.js b/client/src/components/expression/heatmapSquare.js
deleted file mode 100644
index 1200b7cb..00000000
--- a/client/src/components/expression/heatmapSquare.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from "react";
-import getContrast from "font-color-contrast"; // https://www.npmjs.com/package/font-color-contrast
-
-const HeatmapSquare = props => {
- const { backgroundColor, text } = props;
- const contrastColor = getContrast(
- backgroundColor
- .substring(4, backgroundColor.length - 1)
- .replace(/ /g, "")
- .split(",")
- );
- return (
-
- {text}
-
- );
-};
-
-export default HeatmapSquare;
diff --git a/client/src/components/framework/buttons.css b/client/src/components/framework/buttons.css
index 3f65870a..4e9167bf 100644
--- a/client/src/components/framework/buttons.css
+++ b/client/src/components/framework/buttons.css
@@ -1,4 +1,4 @@
-.btn {
+:local(.btn) {
background: none;
cursor: pointer;
color: "#FFF";
diff --git a/client/src/components/framework/container.css b/client/src/components/framework/container.css
index 1338ab8b..2b76dccb 100644
--- a/client/src/components/framework/container.css
+++ b/client/src/components/framework/container.css
@@ -1,3 +1,3 @@
-.container {
+:local(.container) {
min-height: 100%;
}
diff --git a/client/src/components/framework/toasters.js b/client/src/components/framework/toasters.js
new file mode 100644
index 00000000..1a8237dc
--- /dev/null
+++ b/client/src/components/framework/toasters.js
@@ -0,0 +1,12 @@
+import { Position, Toaster, Intent } from "@blueprintjs/core";
+
+/** Singleton toaster instance. Create separate instances for different options. */
+export const ErrorToastTopCenter = Toaster.create({
+ className: "recipe-toaster",
+ position: Position.TOP,
+ intent: Intent.WARNING
+});
+
+export default {
+ ErrorToastTopCenter
+};
diff --git a/client/src/components/geneExpression/cellSetButtons.js b/client/src/components/geneExpression/cellSetButtons.js
new file mode 100644
index 00000000..56e45acb
--- /dev/null
+++ b/client/src/components/geneExpression/cellSetButtons.js
@@ -0,0 +1,46 @@
+// jshint esversion: 6
+import React from "react";
+import _ from "lodash";
+import { Button } from "@blueprintjs/core";
+import { connect } from "react-redux";
+import * as globals from "../../globals";
+
+@connect()
+class CellSetButton extends React.Component {
+ set() {
+ const {
+ differential,
+ crossfilter,
+ dispatch,
+ eitherCellSetOneOrTwo
+ } = this.props;
+
+ const set = _.map(crossfilter.allFiltered(), "name");
+
+ if (!differential.diffExp) {
+ /* diffexp needs to be cleared before we store a new set */
+ dispatch({
+ type: `store current cell selection as differential set ${eitherCellSetOneOrTwo}`,
+ data: set
+ });
+ }
+ }
+
+ render() {
+ const { differential, eitherCellSetOneOrTwo } = this.props;
+ const cellListName = `celllist${eitherCellSetOneOrTwo}`;
+ return (
+
+
+ {eitherCellSetOneOrTwo}
+ {": "}
+ {differential[cellListName]
+ ? `${differential[cellListName].length} cells`
+ : "0 cells"}
+
+
+ );
+ }
+}
+
+export default CellSetButton;
diff --git a/client/src/components/expression/expressionButtons.js b/client/src/components/geneExpression/expressionButtons.js
similarity index 58%
rename from client/src/components/expression/expressionButtons.js
rename to client/src/components/geneExpression/expressionButtons.js
index 9d6c040f..a77dfe1e 100644
--- a/client/src/components/expression/expressionButtons.js
+++ b/client/src/components/geneExpression/expressionButtons.js
@@ -1,6 +1,7 @@
// jshint esversion: 6
import React from "react";
import _ from "lodash";
+import { Button } from "@blueprintjs/core";
import { connect } from "react-redux";
import * as globals from "../../globals";
import actions from "../../actions";
@@ -43,58 +44,32 @@ class Expression extends React.Component {
if (!differential) {
return null;
}
+ const haveBothCellSets =
+ !!differential.celllist1 && !!differential.celllist2;
return (
{!differential.diffExp ? (
-
- {" "}
- Compute Differential Expression{" "}
-
+ Compute Differential Expression
+
) : null}
{differential.diffExp ? (
-
- {" "}
- Clear Differential Expression{" "}
-
+ Clear Differential Expression
+
) : null}
);
diff --git a/client/src/components/geneExpression/index.js b/client/src/components/geneExpression/index.js
index d0252a84..7d44b97a 100644
--- a/client/src/components/geneExpression/index.js
+++ b/client/src/components/geneExpression/index.js
@@ -5,10 +5,11 @@ import React from "react";
import _ from "lodash";
import * as d3 from "d3";
import { connect } from "react-redux";
-import { FaPlusCircle } from "react-icons/fa";
import HistogramBrush from "../brushableHistogram";
import * as globals from "../../globals";
import actions from "../../actions";
+import { ErrorToastTopCenter } from "../framework/toasters";
+import ExpressionButtons from "./expressionButtons";
@connect(state => {
const metadata = _.get(state.controls.world, "obsAnnotations", null);
@@ -45,13 +46,18 @@ class GeneExpression extends React.Component {
const { gene } = this.state;
if (userDefinedGenes.indexOf(gene) !== -1) {
- console.log("That gene already exists");
+ ErrorToastTopCenter.show({
+ message: "That gene already exists"
+ });
} else if (userDefinedGenes.length > 15) {
- console.log(
- "That's too many genes, you can have at most 15 user defined genes"
- );
+ ErrorToastTopCenter.show({
+ message:
+ "That's too many genes, you can have at most 15 user defined genes"
+ });
} else if (!_.find(world.varAnnotations, { name: gene })) {
- console.log("That doesn't appear to be a valid gene name.");
+ ErrorToastTopCenter.show({
+ message: "That doesn't appear to be a valid gene name."
+ });
} else {
dispatch(actions.requestUserDefinedGene(gene));
dispatch({
@@ -68,79 +74,88 @@ class GeneExpression extends React.Component {
return (
-
{
- this.setState({ gene: e.target.value });
- }}
- type="text"
- value={gene}
- />
-
- {" "}
- add gene{" "}
-
- {world && userDefinedGenes.length > 0 ? (
-
User defined genes
- ) : null}
- {world && userDefinedGenes.length > 0
- ? _.map(userDefinedGenes, geneName => {
- const values = world.varDataCache[geneName];
- if (!values) {
- return null;
- }
- return (
-
- );
- })
- : null}
- {differential.diffExp ?
Differentially Expressed Genes
: null}
- {differential.diffExp
- ? _.map(differential.diffExp, value => {
- const annotations = world.varAnnotations[value[0]];
- const { name } = annotations;
- const values = world.varDataCache[name];
- if (!values) {
- return null;
- }
- return (
-
- );
- })
- : null}
+
Custom genes
+
+
+
+ {
+ this.setState({ gene: e.target.value });
+ }}
+ value={gene}
+ type="text"
+ className="bp3-input"
+ placeholder="Add a custom gene"
+ style={{ paddingRight: 94 }}
+ />
+
+
+ Add
+
+
+ {world && userDefinedGenes.length > 0
+ ? _.map(userDefinedGenes, geneName => {
+ const values = world.varDataCache[geneName];
+ if (!values) {
+ return null;
+ }
+ return (
+
+ );
+ })
+ : null}
+
+
+
+ Differentially Expressed Genes
+
+
+ {differential.diffExp
+ ? _.map(differential.diffExp, value => {
+ const annotations = world.varAnnotations[value[0]];
+ const { name } = annotations;
+ const values = world.varDataCache[name];
+ if (!values) {
+ return null;
+ }
+ return (
+
+ );
+ })
+ : null}
+
);
}
diff --git a/client/src/components/graph/graph.css b/client/src/components/graph/graph.css
index 7c207756..e0bebaa2 100644
--- a/client/src/components/graph/graph.css
+++ b/client/src/components/graph/graph.css
@@ -1,4 +1,4 @@
-.graphCanvas path {
+:local(.graphCanvas) path {
shape-rendering: crispEdges;
}
@@ -16,8 +16,8 @@
pointer-events: none;
}
-.axis path,
-.axis line {
+:local(.axis) path,
+:local(.axis) line {
fill: none;
stroke: #000;
stroke-width: 1px;
@@ -29,6 +29,6 @@ circle {
fill: none;
}
-.hidden {
+:local(.hidden) {
display: none;
}
diff --git a/client/src/components/graph/graph.js b/client/src/components/graph/graph.js
index b63553ba..0cf19c33 100644
--- a/client/src/components/graph/graph.js
+++ b/client/src/components/graph/graph.js
@@ -5,10 +5,8 @@ import * as d3 from "d3";
import { connect } from "react-redux";
import mat4 from "gl-mat4";
import _regl from "regl";
+import { Button } from "@blueprintjs/core";
-import { FaCrosshairs, FaSearchPlus } from "react-icons/fa";
-
-import * as globals from "../../globals";
import setupSVGandBrushElements from "./setupSVGandBrush";
import actions from "../../actions";
import _camera from "../../util/camera";
@@ -340,91 +338,48 @@ class Graph extends React.Component {
alignItems: "baseline"
}}
>
-
{
dispatch(actions.resetGraph());
}}
- style={{
- fontSize: 14,
- fontWeight: 400,
- color: "white",
- padding: "0px 10px",
- height: 30,
- marginRight: 10,
- borderRadius: 2,
- backgroundColor: globals.brightBlue,
- border: "none",
- cursor: "pointer"
- }}
>
reset graph
-
-
+ {
dispatch(actions.regraph());
}}
- style={{
- fontSize: 14,
- fontWeight: 400,
- color: "white",
- padding: "0px 10px",
- height: 30,
- marginRight: 10,
- borderRadius: 2,
- backgroundColor: globals.brightBlue,
- border: "none",
- cursor: "pointer"
- }}
>
regraph selection
-
+
-
-
+ {
this.setState({ mode: "brush" });
}}
- style={{
- cursor: "pointer",
- border:
- mode === "brush" ? "1px solid black" : "1px solid white",
- backgroundColor: "white",
- padding: "5px 5px 2px 5px",
- position: "relative",
- top: 2,
- marginRight: 10,
- borderRadius: 3
- }}
- >
- {" "}
- {" "}
-
-
+ {
this.handleBrushDeselectAction();
this.restartReglLoop();
this.setState({ mode: "zoom" });
}}
style={{
- cursor: "pointer",
- border:
- mode === "zoom" ? "1px solid black" : "1px solid white",
- backgroundColor: "white",
- padding: "5px 5px 2px 5px",
- position: "relative",
- top: 2,
- marginRight: 10,
- borderRadius: 3
+ cursor: "pointer"
}}
- >
- {" "}
- {" "}
-
-
+ />
+
diff --git a/client/src/components/leftsidebar.js b/client/src/components/leftsidebar.js
index 4f9cbbc7..346b2fb1 100644
--- a/client/src/components/leftsidebar.js
+++ b/client/src/components/leftsidebar.js
@@ -5,8 +5,6 @@ import { connect } from "react-redux";
import Categorical from "./categorical/categorical";
import Continuous from "./continuous/continuous";
import GeneExpression from "./geneExpression";
-import ExpressionButtons from "./expression/expressionButtons";
-import Heatmap from "./expression/diffExpHeatmap";
import * as globals from "../globals";
import DynamicScatterplot from "./scatterplot/scatterplot";
@@ -37,30 +35,36 @@ class LeftSideBar extends React.Component {
this magic number should be made less fragile,
if cellxgene logo or tabs change, this must as well
*/
- const metadataSectionPadding =
- scatterplotXXaccessor && scatterplotYYaccessor ? 450 : 0;
+ const metadataSectionPadding = 0;
+ // scatterplotXXaccessor && scatterplotYYaccessor ? 450 : 0;
+
return (
-
+
- cellxgene:
- {datasetTitle}
+ cellxgene: {datasetTitle}
+
-
- {scatterplotXXaccessor && scatterplotYYaccessor ? (
-
- ) : null}
-
-
- {currentTab === "metadata" ? : null}
-
+ {scatterplotXXaccessor && scatterplotYYaccessor ? (
+
+ ) : null}
);
}
diff --git a/client/src/components/scatterplot/scatterplot.css b/client/src/components/scatterplot/scatterplot.css
index b567ed53..dab91e0a 100644
--- a/client/src/components/scatterplot/scatterplot.css
+++ b/client/src/components/scatterplot/scatterplot.css
@@ -1,15 +1,14 @@
-
-.scatterplot {
+:local(.scatterplot) {
display: block;
}
-.scatterplot svg,
-.scatterplot canvas {
+:local(.scatterplot) svg,
+:local(.scatterplot) canvas {
font: 10px sans-serif;
position: absolute;
}
-.scatterplot canvas {
+:local(.scatterplot) canvas {
opacity: 0.9;
pointer-events: none;
}
diff --git a/client/src/components/scatterplot/scatterplot.js b/client/src/components/scatterplot/scatterplot.js
index 5985fe12..6dfc67df 100644
--- a/client/src/components/scatterplot/scatterplot.js
+++ b/client/src/components/scatterplot/scatterplot.js
@@ -5,8 +5,10 @@
import React from "react";
import _ from "lodash";
import { connect } from "react-redux";
+import { Button, ButtonGroup } from "@blueprintjs/core";
import _regl from "regl";
import * as d3 from "d3";
+import * as globals from "../../globals";
import _camera from "../../util/camera";
@@ -64,6 +66,7 @@ class Scatterplot extends React.Component {
this.axes = false;
this.state = {
svg: null,
+ minimized: null,
xScale: null,
yScale: null
};
@@ -267,14 +270,48 @@ class Scatterplot extends React.Component {
}
render() {
+ const { dispatch } = this.props;
+ const { minimized } = this.state;
+
return (
+
+ {
+ this.setState({ minimized: !minimized });
+ }}
+ />
+ {
+ dispatch({
+ type: "clear scatterplot"
+ });
+ dispatch({
+ type: "reset colorscale"
+ });
+ }}
+ />
+
>>GLOBAL<<< CSS imports & definitions
+
+Do NOT put anything in this file that is not global. We do not perform
+namespace mangling on these definitions. See webpack config for specifics.
+*/
+@import "~@blueprintjs/core/lib/css/blueprint.css";
+@import "~@blueprintjs/icons/lib/css/blueprint-icons.css";
+@import "~@blueprintjs/select/lib/css/blueprint-select.css";
diff --git a/client/src/index.js b/client/src/index.js
index da4c4fee..aa361610 100644
--- a/client/src/index.js
+++ b/client/src/index.js
@@ -4,6 +4,8 @@ import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
+import "./index.css";
+
/* our code */
import App from "./components/app";
import store from "./reducers";
diff --git a/client/src/reducers/controls.js b/client/src/reducers/controls.js
index 1a9d8da5..0d60fe8d 100644
--- a/client/src/reducers/controls.js
+++ b/client/src/reducers/controls.js
@@ -516,6 +516,12 @@ const Controls = (
...state,
scatterplotYYaccessor: action.data
};
+ case "clear scatterplot":
+ return {
+ ...state,
+ scatterplotXXaccessor: null,
+ scatterplotYYaccessor: null
+ };
default:
return state;