more lint - components (#336)

* more lint

* fix typo introduced in delinting

* more lint

* remove dead code

* lint fixes

* lint
This commit is contained in:
Bruce Martin
2018-10-17 07:17:51 -07:00
committed by GitHub
parent 952578680a
commit f9f43c42c0
23 changed files with 494 additions and 586 deletions
+2 -1
View File
@@ -1,7 +1,7 @@
module.exports = { module.exports = {
root: true, root: true,
parser: "babel-eslint", parser: "babel-eslint",
extends: "airbnb", extends: ["airbnb", "prettier", "prettier/react"],
env: { browser: true, commonjs: true, es6: true }, env: { browser: true, commonjs: true, es6: true },
globals: { expect: true }, globals: { expect: true },
parserOptions: { parserOptions: {
@@ -14,6 +14,7 @@ module.exports = {
}, },
rules: { rules: {
"no-magic-numbers": "off", "no-magic-numbers": "off",
"no-nested-ternary": "off",
"func-style": "off", "func-style": "off",
"arrow-parens": "off", "arrow-parens": "off",
"no-use-before-define": "off", "no-use-before-define": "off",
+46 -29
View File
@@ -2054,7 +2054,7 @@
}, },
"babel-plugin-syntax-object-rest-spread": { "babel-plugin-syntax-object-rest-spread": {
"version": "6.13.0", "version": "6.13.0",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
"dev": true "dev": true
}, },
@@ -2489,7 +2489,7 @@
}, },
"browserify-aes": { "browserify-aes": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -2526,7 +2526,7 @@
}, },
"browserify-rsa": { "browserify-rsa": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -2580,7 +2580,7 @@
}, },
"buffer": { "buffer": {
"version": "4.9.1", "version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -3258,7 +3258,7 @@
}, },
"create-hash": { "create-hash": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -3271,7 +3271,7 @@
}, },
"create-hmac": { "create-hmac": {
"version": "1.1.7", "version": "1.1.7",
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -3945,7 +3945,7 @@
}, },
"diffie-hellman": { "diffie-hellman": {
"version": "5.0.3", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -4376,6 +4376,23 @@
"object.entries": "^1.0.4" "object.entries": "^1.0.4"
} }
}, },
"eslint-config-prettier": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz",
"integrity": "sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w==",
"dev": true,
"requires": {
"get-stdin": "^6.0.0"
},
"dependencies": {
"get-stdin": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
"integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
"dev": true
}
}
},
"eslint-import-resolver-node": { "eslint-import-resolver-node": {
"version": "0.3.2", "version": "0.3.2",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
@@ -4522,7 +4539,7 @@
}, },
"load-json-file": { "load-json-file": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -4699,7 +4716,7 @@
}, },
"events": { "events": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
}, },
"evp_bytestokey": { "evp_bytestokey": {
@@ -4993,7 +5010,7 @@
}, },
"finalhandler": { "finalhandler": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -5717,7 +5734,7 @@
}, },
"get-stream": { "get-stream": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true "dev": true
}, },
@@ -6096,7 +6113,7 @@
}, },
"html-webpack-plugin": { "html-webpack-plugin": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", "resolved": "http://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
"integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -6172,7 +6189,7 @@
}, },
"http-errors": { "http-errors": {
"version": "1.6.3", "version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -6395,7 +6412,7 @@
}, },
"is-builtin-module": { "is-builtin-module": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -7394,7 +7411,7 @@
}, },
"json5": { "json5": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
"dev": true "dev": true
}, },
@@ -7484,7 +7501,7 @@
}, },
"load-json-file": { "load-json-file": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -7813,7 +7830,7 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true "dev": true
} }
@@ -7938,7 +7955,7 @@
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true "dev": true
}, },
@@ -7983,7 +8000,7 @@
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -9695,7 +9712,7 @@
}, },
"parse-asn1": { "parse-asn1": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
"integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -10291,7 +10308,7 @@
}, },
"react-redux": { "react-redux": {
"version": "5.0.7", "version": "5.0.7",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", "resolved": "http://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
"integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==", "integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==",
"requires": { "requires": {
"hoist-non-react-statics": "^2.5.0", "hoist-non-react-statics": "^2.5.0",
@@ -10355,7 +10372,7 @@
}, },
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -11373,7 +11390,7 @@
}, },
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true "dev": true
}, },
@@ -11560,7 +11577,7 @@
}, },
"sha.js": { "sha.js": {
"version": "2.4.11", "version": "2.4.11",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -12014,7 +12031,7 @@
}, },
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -12250,7 +12267,7 @@
}, },
"through": { "through": {
"version": "2.3.8", "version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true "dev": true
}, },
@@ -12889,7 +12906,7 @@
"dependencies": { "dependencies": {
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true "dev": true
} }
@@ -13547,7 +13564,7 @@
}, },
"wrap-ansi": { "wrap-ansi": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -13655,7 +13672,7 @@
}, },
"yargs": { "yargs": {
"version": "11.1.0", "version": "11.1.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
"integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
"dev": true, "dev": true,
"requires": { "requires": {
+1
View File
@@ -77,6 +77,7 @@
"css-loader": "^1.0.0", "css-loader": "^1.0.0",
"eslint": "^5.3.0", "eslint": "^5.3.0",
"eslint-config-airbnb": "^17.1.0", "eslint-config-airbnb": "^17.1.0",
"eslint-config-prettier": "^3.1.0",
"eslint-loader": "^2.1.1", "eslint-loader": "^2.1.1",
"eslint-plugin-filenames": "^1.3.2", "eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-import": "^2.14.0", "eslint-plugin-import": "^2.14.0",
@@ -7,10 +7,10 @@ https://bl.ocks.org/SpaceActuary/2f004899ea1b2bd78d6f1dbb2febf771
import React from "react"; import React from "react";
import _ from "lodash"; import _ from "lodash";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { kvCache } from "../../util/stateManager/";
import { FaPaintBrush } from "react-icons/fa"; import { FaPaintBrush } from "react-icons/fa";
import * as d3 from "d3"; import * as d3 from "d3";
import memoize from "memoize-one"; import memoize from "memoize-one";
import { kvCache } from "../../util/stateManager";
import * as globals from "../../globals"; import * as globals from "../../globals";
import actions from "../../actions"; import actions from "../../actions";
@@ -33,7 +33,6 @@ class HistogramBrush extends React.Component {
histogramCache.y = d3 histogramCache.y = d3
.scaleLinear() .scaleLinear()
.range([this.height - this.marginBottom, 0]); .range([this.height - this.marginBottom, 0]);
// .range([height - margin.bottom, margin.top]);
if (obsAnnotations[0][field]) { if (obsAnnotations[0][field]) {
// recalculate expensive stuff // recalculate expensive stuff
@@ -116,6 +115,7 @@ class HistogramBrush extends React.Component {
drawHistogram(svgRef) { drawHistogram(svgRef) {
const { obsAnnotations, field, ranges } = this.props; const { obsAnnotations, field, ranges } = this.props;
const { brush, axis } = this.state;
const histogramCache = this.calcHistogramCache( const histogramCache = this.calcHistogramCache(
obsAnnotations, obsAnnotations,
field, field,
@@ -140,8 +140,8 @@ class HistogramBrush extends React.Component {
.attr("width", d => Math.abs(x(d.x1) - x(d.x0) - 1)) .attr("width", d => Math.abs(x(d.x1) - x(d.x0) - 1))
.attr("height", d => y(0) - y(d.length / numValues)); .attr("height", d => y(0) - y(d.length / numValues));
if (!this.state.brush && !this.state.axis) { if (!brush && !axis) {
const brush = d3 const newBrush = d3
.select(svgRef) .select(svgRef)
.append("g") .append("g")
.attr("class", "brush") .attr("class", "brush")
@@ -153,12 +153,6 @@ class HistogramBrush extends React.Component {
.attr("class", "axis axis--x") .attr("class", "axis axis--x")
.attr("transform", `translate(0,${this.height - this.marginBottom})`) .attr("transform", `translate(0,${this.height - this.marginBottom})`)
.call(d3.axisBottom(x).ticks(5)); .call(d3.axisBottom(x).ticks(5));
// .append("text")
// .attr("x", this.width - 2)
// .attr("y", -6)
// .attr("fill", "#000")
// // .attr("text-anchor", "end")
// // .text(field);
d3.select(svgRef) d3.select(svgRef)
.selectAll(".axis--x text") .selectAll(".axis--x text")
@@ -173,14 +167,13 @@ class HistogramBrush extends React.Component {
.selectAll(".axis--x line") .selectAll(".axis--x line")
.style("stroke", "rgb(230,230,230)"); .style("stroke", "rgb(230,230,230)");
this.setState({ brush, xAxis }); this.setState({ brush: newBrush, xAxis }); // eslint-disable-line react/no-unused-state
} }
} }
handleColorAction() { handleColorAction() {
const { const {
obsAnnotations, obsAnnotations,
ranges,
dispatch, dispatch,
field, field,
world, world,
@@ -1,26 +0,0 @@
import * as globals from "../../globals";
import _ from "lodash";
import * as constants from "./constants";
export const calcHistogram = (ranges, allValuesForContinuousFieldAsArray) => {
const histogramData = {};
histogramData.x = d3
.scaleLinear()
.domain([ranges.min, ranges.max])
.range([0, constants.width]);
histogramData.y = d3
.scaleLinear()
.range([constants.height - constants.marginBottom, 0]);
// .range([height - margin.bottom, margin.top]);
histogramData.bins = d3
.histogram()
.domain(histogramData.x.domain())
.thresholds(40)(allValuesForContinuousFieldAsArray);
histogramData.numValues = allValuesForContinuousFieldAsArray.length;
return histogramData;
};
@@ -3,169 +3,7 @@ import React from "react";
import _ from "lodash"; import _ from "lodash";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { FaChevronRight, FaChevronDown, FaPaintBrush } from "react-icons/fa"; import Category from "./category";
import * as globals from "../../globals";
import Value from "./value";
import { alphabeticallySortedValues } from "./util";
@connect(state => ({
colorAccessor: state.controls.colorAccessor,
categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap
}))
class Category extends React.Component {
constructor(props) {
super(props);
this.state = {
isChecked: true,
isExpanded: false
};
}
componentDidUpdate() {
const { categoricalAsBooleansMap, metadataField } = this.props;
const valuesAsBool = _.values(categoricalAsBooleansMap[metadataField]);
/* count categories toggled on by counting true values */
const categoriesToggledOn = _.values(valuesAsBool).filter(v => v).length;
if (categoriesToggledOn === valuesAsBool.length) {
/* everything is on, so not indeterminate */
this.checkbox.indeterminate = false;
} else if (categoriesToggledOn === 0) {
/* nothing is on, so no */
this.checkbox.indeterminate = false;
} else if (categoriesToggledOn < valuesAsBool.length) {
/* to be explicit... */
this.checkbox.indeterminate = true;
}
}
handleColorChange() {
const { dispatch, metadataField } = this.props;
dispatch({
type: "color by categorical metadata",
colorAccessor: metadataField
});
}
toggleAll() {
const { dispatch, metadataField } = this.props;
dispatch({
type: "categorical metadata filter all of these",
metadataField
});
this.setState({ isChecked: true });
}
toggleNone() {
const { dispatch, metadataField, value } = this.props;
dispatch({
type: "categorical metadata filter none of these",
metadataField,
value
});
this.setState({ isChecked: false });
}
handleToggleAllClick() {
const { isChecked } = this.state;
// || this.checkbox.indeterminate === false
if (isChecked) {
this.toggleNone();
} else if (!isChecked) {
this.toggleAll();
}
}
renderCategoryItems() {
const { values, metadataField } = this.props;
return _.map(alphabeticallySortedValues(values), (v, i) => (
<Value
key={v}
metadataField={metadataField}
count={values[v]}
value={v}
i={i}
/>
));
}
render() {
const { isExpanded, isChecked } = this.state;
const { metadataField, colorAccessor } = this.props;
return (
<div
style={{
// display: "flex",
// alignItems: "baseline",
maxWidth: globals.maxControlsWidth
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline"
}}
>
<p
style={{
// flexShrink: 0,
fontWeight: 500,
// textAlign: "right",
// fontFamily: globals.accentFont,
// fontStyle: "italic",
margin: "3px 10px 3px 0px"
}}
>
<span
style={{
cursor: "pointer",
display: "inline-block",
position: "relative",
top: 2
}}
onClick={() => {
this.setState({ isExpanded: !isExpanded });
}}
>
{isExpanded ? <FaChevronDown /> : <FaChevronRight />}
</span>
{metadataField}
<input
onChange={this.handleToggleAllClick.bind(this)}
ref={el => (this.checkbox = el)}
checked={isChecked}
type="checkbox"
/>
<span
onClick={this.handleColorChange.bind(this)}
style={{
fontSize: 14,
marginLeft: 4,
// padding: this.props.colorAccessor === this.props.metadataField ? 3 : "auto",
borderRadius: 3,
color:
colorAccessor === metadataField
? globals.brightBlue
: "black",
// backgroundColor: this.props.colorAccessor === this.props.metadataField ? globals.brightBlue : "inherit",
display: "inline-block",
position: "relative",
top: 2,
cursor: "pointer"
}}
>
<FaPaintBrush />
</span>
</p>
</div>
<div>{isExpanded ? this.renderCategoryItems() : null}</div>
</div>
);
}
}
@connect(state => { @connect(state => {
const ranges = _.get(state.controls.world, "summary.obs", null); const ranges = _.get(state.controls.world, "summary.obs", null);
@@ -202,6 +40,7 @@ class Categories extends React.Component {
<Category key={key} metadataField={key} values={value.options} /> <Category key={key} metadataField={key} values={value.options} />
); );
} }
return undefined;
})} })}
</div> </div>
); );
@@ -0,0 +1,171 @@
import React from "react";
import _ from "lodash";
import { connect } from "react-redux";
import { FaChevronRight, FaChevronDown, FaPaintBrush } from "react-icons/fa";
import * as globals from "../../globals";
import Value from "./value";
import alphabeticallySortedValues from "./util";
@connect(state => ({
colorAccessor: state.controls.colorAccessor,
categoricalAsBooleansMap: state.controls.categoricalAsBooleansMap
}))
class Category extends React.Component {
constructor(props) {
super(props);
this.state = {
isChecked: true,
isExpanded: false
};
}
componentDidUpdate() {
const { categoricalAsBooleansMap, metadataField } = this.props;
const valuesAsBool = _.values(categoricalAsBooleansMap[metadataField]);
/* count categories toggled on by counting true values */
const categoriesToggledOn = _.values(valuesAsBool).filter(v => v).length;
if (categoriesToggledOn === valuesAsBool.length) {
/* everything is on, so not indeterminate */
this.checkbox.indeterminate = false;
} else if (categoriesToggledOn === 0) {
/* nothing is on, so no */
this.checkbox.indeterminate = false;
} else if (categoriesToggledOn < valuesAsBool.length) {
/* to be explicit... */
this.checkbox.indeterminate = true;
}
}
handleColorChange() {
const { dispatch, metadataField } = this.props;
dispatch({
type: "color by categorical metadata",
colorAccessor: metadataField
});
}
toggleAll() {
const { dispatch, metadataField } = this.props;
dispatch({
type: "categorical metadata filter all of these",
metadataField
});
this.setState({ isChecked: true });
}
toggleNone() {
const { dispatch, metadataField, value } = this.props;
dispatch({
type: "categorical metadata filter none of these",
metadataField,
value
});
this.setState({ isChecked: false });
}
handleToggleAllClick() {
const { isChecked } = this.state;
// || this.checkbox.indeterminate === false
if (isChecked) {
this.toggleNone();
} else if (!isChecked) {
this.toggleAll();
}
}
renderCategoryItems() {
const { values, metadataField } = this.props;
return _.map(alphabeticallySortedValues(values), (v, i) => (
<Value
key={v}
metadataField={metadataField}
count={values[v]}
value={v}
i={i}
/>
));
}
render() {
const { isExpanded, isChecked } = this.state;
const { metadataField, colorAccessor } = this.props;
return (
<div
style={{
// display: "flex",
// alignItems: "baseline",
maxWidth: globals.maxControlsWidth
}}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline"
}}
>
<p
style={{
// flexShrink: 0,
fontWeight: 500,
// textAlign: "right",
// fontFamily: globals.accentFont,
// fontStyle: "italic",
margin: "3px 10px 3px 0px"
}}
>
<span
style={{
cursor: "pointer",
display: "inline-block",
position: "relative",
top: 2
}}
onClick={() => {
this.setState({ isExpanded: !isExpanded });
}}
>
{isExpanded ? <FaChevronDown /> : <FaChevronRight />}
</span>
{metadataField}
<input
onChange={this.handleToggleAllClick.bind(this)}
ref={el => {
this.checkbox = el;
return el;
}}
checked={isChecked}
type="checkbox"
/>
<span
onClick={this.handleColorChange.bind(this)}
style={{
fontSize: 14,
marginLeft: 4,
// padding: this.props.colorAccessor === this.props.metadataField ? 3 : "auto",
borderRadius: 3,
color:
colorAccessor === metadataField
? globals.brightBlue
: "black",
// backgroundColor: this.props.colorAccessor === this.props.metadataField ? globals.brightBlue : "inherit",
display: "inline-block",
position: "relative",
top: 2,
cursor: "pointer"
}}
>
<FaPaintBrush />
</span>
</p>
</div>
<div>{isExpanded ? this.renderCategoryItems() : null}</div>
</div>
);
}
}
export default Category;
+1 -1
View File
@@ -1,5 +1,5 @@
// jshint esversion: 6 // jshint esversion: 6
export const alphabeticallySortedValues = values => export default values =>
Object.keys(values).sort((a, b) => { Object.keys(values).sort((a, b) => {
const textA = a.toUpperCase(); const textA = a.toUpperCase();
const textB = b.toUpperCase(); const textB = b.toUpperCase();
+15 -14
View File
@@ -5,18 +5,16 @@ import React from "react";
import _ from "lodash"; import _ from "lodash";
import { connect } from "react-redux"; import { connect } from "react-redux";
import HistogramBrush from "../brushableHistogram/"; import HistogramBrush from "../brushableHistogram";
@connect(state => { @connect(state => ({
return { ranges: _.get(state.controls.world, "summary.obs", null),
ranges: _.get(state.controls.world, "summary.obs", null), metadata: _.get(state.controls.world, "obsAnnotations", null),
metadata: _.get(state.controls.world, "obsAnnotations", null), colorAccessor: state.controls.colorAccessor,
colorAccessor: state.controls.colorAccessor, colorScale: state.controls.colorScale,
colorScale: state.controls.colorScale, selectionUpdate: _.get(state.controls, "crossfilter.updateTime", null),
selectionUpdate: _.get(state.controls, "crossfilter.updateTime", null), schema: _.get(state.controls.world, "schema", null)
schema: _.get(state.controls.world, "schema", null) }))
};
})
class Continuous extends React.Component { class Continuous extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -26,6 +24,8 @@ class Continuous extends React.Component {
this.state = {}; this.state = {};
} }
componentDidUpdate() {}
handleColorAction(key) { handleColorAction(key) {
return () => { return () => {
const { dispatch, ranges } = this.props; const { dispatch, ranges } = this.props;
@@ -40,9 +40,10 @@ class Continuous extends React.Component {
render() { render() {
const { ranges, obsAnnotations, schema } = this.props; const { ranges, obsAnnotations, schema } = this.props;
if (schema && !this.continuousChecked) { if (schema && !this.continuousChecked) {
this.hasContinuous = _.some(schema.annotations.obs, d => { this.hasContinuous = _.some(
return d.type === "int32" || d.type === "float32"; schema.annotations.obs,
}); d => d.type === "int32" || d.type === "float32"
);
this.continuousChecked = true; /* only do this once */ this.continuousChecked = true; /* only do this once */
} }
+2 -4
View File
@@ -39,10 +39,8 @@ export const brushstart = () => {
d3.event.sourceEvent.stopPropagation(); d3.event.sourceEvent.stopPropagation();
}; };
export const d3_functor = v => { // Unused.
return typeof v === "function" ? v : () => v; // export const d3_functor = v => (typeof v === "function" ? v : () => v);
};
export const project = (d, dimensions, xscale) => export const project = (d, dimensions, xscale) =>
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
@@ -3,32 +3,35 @@ import React from "react";
import _ from "lodash"; import _ from "lodash";
import { connect } from "react-redux"; import { connect } from "react-redux";
import * as globals from "../../globals"; import * as globals from "../../globals";
import styles from "../framework/buttons.css";
import actions from "../../actions";
@connect() @connect()
class CellSetButton extends React.Component { class CellSetButton extends React.Component {
set() { set() {
const { differential } = this.props; const {
differential,
crossfilter,
dispatch,
eitherCellSetOneOrTwo
} = this.props;
const set = _.map(this.props.crossfilter.allFiltered(), "name"); const set = _.map(crossfilter.allFiltered(), "name");
if (!differential.diffExp) { if (!differential.diffExp) {
/* diffexp needs to be cleared before we store a new set */ /* diffexp needs to be cleared before we store a new set */
this.props.dispatch({ dispatch({
type: type: `store current cell selection as differential set ${eitherCellSetOneOrTwo}`,
"store current cell selection as differential set " +
this.props.eitherCellSetOneOrTwo,
data: set data: set
}); });
} }
} }
render() { render() {
const { differential } = this.props; const { differential, eitherCellSetOneOrTwo } = this.props;
const cellListName = `celllist${eitherCellSetOneOrTwo}`;
return ( return (
<span style={{ marginRight: 10 }}> <span style={{ marginRight: 10 }}>
<button <button
type="button"
style={{ style={{
color: "#FFF", color: "#FFF",
borderRadius: 2, borderRadius: 2,
@@ -44,7 +47,7 @@ class CellSetButton extends React.Component {
> >
<span style={{ fontSize: 14, fontWeight: 700 }}> <span style={{ fontSize: 14, fontWeight: 700 }}>
{" "} {" "}
{this.props.eitherCellSetOneOrTwo} {eitherCellSetOneOrTwo}
{": "} {": "}
</span> </span>
<span <span
@@ -55,13 +58,9 @@ class CellSetButton extends React.Component {
top: 0 top: 0
}} }}
> >
{differential[ {differential[cellListName]
"celllist" + this.props.eitherCellSetOneOrTwo ? `${differential[cellListName].length} cells`
] : "0 cells"}
? this.props.differential[
"celllist" + this.props.eitherCellSetOneOrTwo
].length + " cells"
: 0 + " cells"}
</span> </span>
</button> </button>
</span> </span>
@@ -70,17 +69,3 @@ class CellSetButton extends React.Component {
} }
export default CellSetButton; export default CellSetButton;
//
// <button style={{
// marginLeft: 3,
// color: "#FFF",
// padding: "0px 10px",
// height: 30,
// backgroundColor: globals.brightBlue,
// border: "none",
// cursor: "pointer",
// }}>
// <span style={{fontSize: 24, fontWeight: 700}}> X </span>
//
// </button>
@@ -1,203 +1,10 @@
// jshint esversion: 6 // jshint esversion: 6
import React from "react"; import React from "react";
import _ from "lodash"; import _ from "lodash";
import memoize from "memoize-one";
import { connect } from "react-redux"; import { connect } from "react-redux";
// import ReactAutocomplete from "react-autocomplete"; /* http://emilebres.github.io/react-virtualized-checkbox/ */
import getContrast from "font-color-contrast"; // https://www.npmjs.com/package/font-color-contrast
import { FaPaintBrush } from "react-icons/fa";
import * as d3 from "d3"; import * as d3 from "d3";
import { interpolateGreys } from "d3-scale-chromatic"; import { interpolateGreys } from "d3-scale-chromatic";
import * as globals from "../../globals"; import HeatmapRow from "./heatmapRow";
import actions from "../../actions";
class HeatmapSquare extends React.Component {
constructor(props) {
super(props);
this.state = {
value: ""
};
}
render() {
const { backgroundColor, text } = this.props;
const contrastColor = getContrast(
backgroundColor
.substring(4, backgroundColor.length - 1)
.replace(/ /g, "")
.split(",")
);
return (
<p
style={{
padding: "12px 6px",
textAlign: "center",
color: contrastColor,
width: 40,
flexShrink: 0,
fontSize: 12,
margin: 0,
backgroundColor
}}
>
{text}
</p>
);
}
}
/**********************************
***********************************
***********************************
Row
***********************************
***********************************
**********************************/
@connect(state => ({
scatterplotXXaccessor: state.controls.scatterplotXXaccessor,
scatterplotYYaccessor: state.controls.scatterplotYYaccessor,
colorAccessor: state.controls.colorAccessor
}))
class HeatmapRow extends React.Component {
constructor(props) {
super(props);
this.state = {
value: ""
};
}
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 (
<div
style={{
width: 220,
display: "flex",
justifyContent: "flex-start",
alignItems: "baseline"
}}
>
<div style={{ width: 150, flexShrink: 0 }}>
<span
style={{
fontSize: 14
}}
>
{gene}
</span>
</div>
<HeatmapSquare
backgroundColor={greyColorScale(set1exp)}
text={set1exp.toPrecision(2)}
/>
<HeatmapSquare
backgroundColor={greyColorScale(set2exp)}
text={set2exp.toPrecision(2)}
/>
<span
title={aveDiff}
style={{
fontSize: 12,
marginLeft: 10,
marginRight: 10
}}
>
{aveDiff.toFixed(2)}
</span>
<span
onClick={this.handleSetGeneAsScatterplotX(gene).bind(this)}
style={{
fontSize: 16,
color:
scatterplotXXaccessor === gene ? "white" : globals.brightBlue,
cursor: "pointer",
position: "relative",
top: 1,
fontWeight: 700,
marginRight: 4,
borderRadius: 3,
padding: "2px 3px",
backgroundColor:
scatterplotXXaccessor === gene ? globals.brightBlue : "inherit"
}}
>
X
</span>
<span
onClick={this.handleSetGeneAsScatterplotY(gene).bind(this)}
style={{
fontSize: 16,
color:
scatterplotYYaccessor === gene ? "white" : globals.brightBlue,
cursor: "pointer",
position: "relative",
top: 1,
fontWeight: 700,
marginRight: 4,
borderRadius: 3,
padding: "2px 3px",
backgroundColor:
scatterplotYYaccessor === gene ? globals.brightBlue : "inherit"
}}
>
Y
</span>
<span
onClick={this.handleGeneColorScaleClick(gene).bind(this)}
style={{
fontSize: 16,
cursor: "pointer",
position: "relative",
marginRight: 6,
borderRadius: 3,
padding: "0px 2px 2px 2px",
color: colorAccessor === gene ? "white" : "inherit",
backgroundColor:
colorAccessor === gene ? globals.brightBlue : "inherit"
}}
>
<FaPaintBrush style={{ display: "inline-block" }} />
</span>
</div>
);
}
}
/********************************** /**********************************
*********************************** ***********************************
@@ -212,18 +19,6 @@ class HeatmapRow extends React.Component {
world: state.controls.world world: state.controls.world
})) }))
class Heatmap extends React.Component { class Heatmap extends React.Component {
constructor(props) {
super(props);
this.state = {
value: ""
};
}
// XXX TODO unused at the moment
// getAllGeneNames = memoize(world =>
// _.map(this.props.world.varAnnotations, "name")
// );
render() { render() {
const { world, differential } = this.props; const { world, differential } = this.props;
if (!differential.diffExp) { if (!differential.diffExp) {
@@ -0,0 +1,154 @@
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 (
<div
style={{
width: 220,
display: "flex",
justifyContent: "flex-start",
alignItems: "baseline"
}}
>
<div style={{ width: 150, flexShrink: 0 }}>
<span
style={{
fontSize: 14
}}
>
{gene}
</span>
</div>
<HeatmapSquare
backgroundColor={greyColorScale(set1exp)}
text={set1exp.toPrecision(2)}
/>
<HeatmapSquare
backgroundColor={greyColorScale(set2exp)}
text={set2exp.toPrecision(2)}
/>
<span
title={aveDiff}
style={{
fontSize: 12,
marginLeft: 10,
marginRight: 10
}}
>
{aveDiff.toFixed(2)}
</span>
<span
onClick={this.handleSetGeneAsScatterplotX(gene).bind(this)}
style={{
fontSize: 16,
color:
scatterplotXXaccessor === gene ? "white" : globals.brightBlue,
cursor: "pointer",
position: "relative",
top: 1,
fontWeight: 700,
marginRight: 4,
borderRadius: 3,
padding: "2px 3px",
backgroundColor:
scatterplotXXaccessor === gene ? globals.brightBlue : "inherit"
}}
>
X
</span>
<span
onClick={this.handleSetGeneAsScatterplotY(gene).bind(this)}
style={{
fontSize: 16,
color:
scatterplotYYaccessor === gene ? "white" : globals.brightBlue,
cursor: "pointer",
position: "relative",
top: 1,
fontWeight: 700,
marginRight: 4,
borderRadius: 3,
padding: "2px 3px",
backgroundColor:
scatterplotYYaccessor === gene ? globals.brightBlue : "inherit"
}}
>
Y
</span>
<span
onClick={this.handleGeneColorScaleClick(gene).bind(this)}
style={{
fontSize: 16,
cursor: "pointer",
position: "relative",
marginRight: 6,
borderRadius: 3,
padding: "0px 2px 2px 2px",
color: colorAccessor === gene ? "white" : "inherit",
backgroundColor:
colorAccessor === gene ? globals.brightBlue : "inherit"
}}
>
<FaPaintBrush style={{ display: "inline-block" }} />
</span>
</div>
);
}
}
export default HeatmapRow;
@@ -0,0 +1,30 @@
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 (
<p
style={{
padding: "12px 6px",
textAlign: "center",
color: contrastColor,
width: 40,
flexShrink: 0,
fontSize: 12,
margin: 0,
backgroundColor
}}
>
{text}
</p>
);
};
export default HeatmapSquare;
+28 -75
View File
@@ -8,7 +8,6 @@ import { connect } from "react-redux";
import { FaPlusCircle } from "react-icons/fa"; import { FaPlusCircle } from "react-icons/fa";
import HistogramBrush from "../brushableHistogram"; import HistogramBrush from "../brushableHistogram";
import * as globals from "../../globals"; import * as globals from "../../globals";
// import ReactAutocomplete from "react-autocomplete"; /* http://emilebres.github.io/react-virtualized-checkbox/ */
import actions from "../../actions"; import actions from "../../actions";
@connect(state => { @connect(state => {
@@ -64,7 +63,7 @@ class GeneExpression extends React.Component {
} }
render() { render() {
const { world, userDefinedGenes } = this.props; const { world, userDefinedGenes, differential } = this.props;
const { gene } = this.state; const { gene } = this.state;
return ( return (
@@ -106,43 +105,40 @@ class GeneExpression extends React.Component {
) : null} ) : null}
{world && userDefinedGenes.length > 0 {world && userDefinedGenes.length > 0
? _.map(userDefinedGenes, geneName => { ? _.map(userDefinedGenes, geneName => {
if (!world.varDataCache[geneName]) { const values = world.varDataCache[geneName];
if (!values) {
return null; return null;
} else {
const values = world.varDataCache[geneName];
return (
<HistogramBrush
key={geneName}
field={geneName}
ranges={d3.extent(values)}
isUserDefined
/>
);
} }
return (
<HistogramBrush
key={geneName}
field={geneName}
ranges={d3.extent(values)}
isUserDefined
/>
);
}) })
: null} : null}
{this.props.differential.diffExp ? ( {differential.diffExp ? <p> Differentially Expressed Genes </p> : null}
<p> Differentially Expressed Genes </p> {differential.diffExp
) : null} ? _.map(differential.diffExp, value => {
{this.props.differential.diffExp const annotations = world.varAnnotations[value[0]];
? _.map(this.props.differential.diffExp, (value, key) => { const { name } = annotations;
const name = world.varAnnotations[value[0]].name;
const values = world.varDataCache[name]; const values = world.varDataCache[name];
if (!world.varDataCache[world.varAnnotations[value[0]].name]) { if (!values) {
return null; return null;
} else {
return (
<HistogramBrush
key={name}
field={name}
ranges={d3.extent(values)}
isDiffExp
diffExp_avgDiff={value[1]}
diffExp_set1AvgExp={value[4]}
diffExp_set2AvgExp={value[5]}
/>
);
} }
return (
<HistogramBrush
key={name}
field={name}
ranges={d3.extent(values)}
isDiffExp
diffExp_avgDiff={value[1]}
diffExp_set1AvgExp={value[4]}
diffExp_set2AvgExp={value[5]}
/>
);
}) })
: null} : null}
</div> </div>
@@ -151,46 +147,3 @@ class GeneExpression extends React.Component {
} }
export default GeneExpression; export default GeneExpression;
// <ReactAutocomplete
// items={this.props.allGeneNames}
// shouldItemRender={(item, value) =>
// item.toLowerCase().indexOf(value.toLowerCase()) > -1
// }
// getItemValue={item => item}
// renderItem={(item, highlighted) => (
// <div
// key={item}
// style={{
// backgroundColor: highlighted ? "#eee" : "transparent"
// }}
// >
// {item}
// </div>
// )}
// value={this.state.value}
// onChange={e => this.setState({ value: e.target.value })}
// onSelect={value => {
// this.setState({ value });
// this.props.dispatch(
// actions.requestSingleGeneExpressionCountsPOST(
// value
// )
// );
// }}
// />
// <div>
// {_.map(this.props.ranges, (value, key) => {
// const isColorField = key.includes("color") || key.includes("Color");
// if (value.range && key !== "CellName" && !isColorField) {
// return (
// <HistogramBrush
// key={key}
// metadataField={key}
// ranges={value.range}
// />
// );
// }
// })}
// </div>
+3 -4
View File
@@ -6,8 +6,7 @@ import { connect } from "react-redux";
import mat4 from "gl-mat4"; import mat4 from "gl-mat4";
import _regl from "regl"; import _regl from "regl";
import { FaCrosshairs } from "react-icons/fa"; import { FaCrosshairs, FaSearchPlus } from "react-icons/fa";
import { FaSearchPlus } from "react-icons/fa";
import * as globals from "../../globals"; import * as globals from "../../globals";
import setupSVGandBrushElements from "./setupSVGandBrush"; import setupSVGandBrushElements from "./setupSVGandBrush";
@@ -192,13 +191,13 @@ class Graph extends React.Component {
d3.select("#graphAttachPoint") d3.select("#graphAttachPoint")
.selectAll("svg") .selectAll("svg")
.remove(); .remove();
const { svg, brush, brushContainer } = setupSVGandBrushElements( const { svg: newSvg, brush, brushContainer } = setupSVGandBrushElements(
this.handleBrushSelectAction.bind(this), this.handleBrushSelectAction.bind(this),
this.handleBrushDeselectAction.bind(this), this.handleBrushDeselectAction.bind(this),
responsive, responsive,
this.graphPaddingTop this.graphPaddingTop
); );
this.setState({ svg, brush, brushContainer }); this.setState({ svg: newSvg, brush, brushContainer });
} }
} }
@@ -38,15 +38,14 @@ export default function(regl) {
uniforms: { uniforms: {
distance: regl.prop("distance"), distance: regl.prop("distance"),
view: regl.prop("view"), view: regl.prop("view"),
projection: (context, props) => { projection: (context, props) =>
return mat4.perspective( mat4.perspective(
[], [],
Math.PI / 2, Math.PI / 2,
context.viewportWidth * props.scale / context.viewportHeight, (context.viewportWidth * props.scale) / context.viewportHeight,
0.01, 0.01,
1000 1000
); )
}
}, },
count: regl.prop("count"), count: regl.prop("count"),
@@ -238,7 +238,7 @@ class Scatterplot extends React.Component {
// and it's alread defined to be a bottom axis. // and it's alread defined to be a bottom axis.
svg svg
.append("g") .append("g")
.attr("transform", "translate(0," + height + ")") .attr("transform", `translate(0,${height})`)
.attr("class", "x axis") .attr("class", "x axis")
.call(xAxis); .call(xAxis);
@@ -279,8 +279,8 @@ class Scatterplot extends React.Component {
className={styles.scatterplot} className={styles.scatterplot}
id="scatterplot" id="scatterplot"
style={{ style={{
width: width + margin.left + margin.right + "px", width: `${width + margin.left + margin.right}px`,
height: height + margin.top + margin.bottom + "px" height: `${height + margin.top + margin.bottom}px`
}} }}
> >
<canvas <canvas
@@ -8,14 +8,14 @@
import * as d3 from "d3"; import * as d3 from "d3";
const setupScatterplot = (width, height, margin) => { const setupScatterplot = (width, height, margin) => {
var container = d3.select("#scatterplot"); const container = d3.select("#scatterplot");
var svg = container 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})`);
return { return {
svg svg
@@ -1,9 +1,4 @@
// jshint esversion: 6 // jshint esversion: 6
import _ from "lodash";
const paddingRight = 120;
const continuousChartWidth = 340;
export const margin = { top: 66, right: 110, bottom: 20, left: 60 }; export const margin = { top: 66, right: 110, bottom: 20, left: 60 };
export const width = 340; export const width = 340;
export const height = 340 - margin.top - margin.bottom; export const height = 340 - margin.top - margin.bottom;
+3 -3
View File
@@ -279,14 +279,14 @@ class ScalarDimension {
let found = 0; let found = 0;
// skip up to offset records // skip up to offset records
for (i = len - 1; 0 <= i && skip < offset; i -= 1) { for (i = len - 1; i >= 0 && skip < offset; i -= 1) {
if (selection.isSelected(index[i])) { if (selection.isSelected(index[i])) {
skip += 1; skip += 1;
} }
} }
// grab up to k records // grab up to k records
for (; 0 <= i && found < k; i -= 1) { for (; i >= 0 && found < k; i -= 1) {
if (selection.isSelected(index[i])) { if (selection.isSelected(index[i])) {
ret.push(data[index[i]]); ret.push(data[index[i]]);
found += 1; found += 1;
@@ -539,7 +539,7 @@ class ScalarGroup {
// set the reduce functions to count records. // set the reduce functions to count records.
reduceCount() { reduceCount() {
return this.reduce((p, v) => p + 1, (p, v) => p - 1, () => 0); return this.reduce(p => p + 1, p => p - 1, () => 0);
} }
// set the reduce functions to sum records using specified value accessor. // set the reduce functions to sum records using specified value accessor.
@@ -30,7 +30,7 @@ class PositiveIntervals {
res.push(copy[i]); res.push(copy[i]);
} else if (copy[i][1] > res[res.length - 1][1]) { } else if (copy[i][1] > res[res.length - 1][1]) {
// merge this into previous // merge this into previous
res[res.length - 1][1] = copy[i][1]; res[res.length - 1][1] = copy[i][1]; // eslint-disable-line prefer-destructuring
} }
} }
return res; return res;
+3
View File
@@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}