diff --git a/README.md b/README.md
index bad451b7..3760f426 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,12 @@
[![PyPI](https://img.shields.io/pypi/pyversions/dtale.svg)](https://pypi.python.org/pypi/dtale/)
[![ReadTheDocs](https://readthedocs.org/projects/dtale/badge)](https://dtale.readthedocs.io)
[![codecov](https://codecov.io/gh/manahl/dtale/branch/master/graph/badge.svg)](https://codecov.io/gh/manahl/dtale)
+[![Downloads](https://pepy.tech/badge/dtale)](https://pepy.tech/project/dtale)
## Getting Started
+![](https://raw.githubusercontent.com/manahl/dtale/master/docs/images/blog/dtale_demo_mini.gif)
+
Setup/Activate your environment and install the egg
```bash
diff --git a/docs/images/blog/dtale_demo_mini.gif b/docs/images/blog/dtale_demo_mini.gif
new file mode 100644
index 00000000..dce66644
Binary files /dev/null and b/docs/images/blog/dtale_demo_mini.gif differ
diff --git a/static/__tests__/dtale/DataViewer-reload-test.jsx b/static/__tests__/dtale/DataViewer-reload-test.jsx
new file mode 100644
index 00000000..a0e3eb94
--- /dev/null
+++ b/static/__tests__/dtale/DataViewer-reload-test.jsx
@@ -0,0 +1,101 @@
+import { mount } from "enzyme";
+import _ from "lodash";
+import React from "react";
+import { Provider } from "react-redux";
+
+import { RemovableError } from "../../RemovableError";
+import mockPopsicle from "../MockPopsicle";
+import * as t from "../jest-assertions";
+import reduxUtils from "../redux-test-utils";
+import { withGlobalJquery } from "../test-utils";
+
+const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "offsetHeight");
+const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "offsetWidth");
+
+describe("DataViewer tests", () => {
+ beforeAll(() => {
+ Object.defineProperty(HTMLElement.prototype, "offsetHeight", { configurable: true, value: 500 });
+ Object.defineProperty(HTMLElement.prototype, "offsetWidth", { configurable: true, value: 500 });
+
+ const mockBuildLibs = withGlobalJquery(() =>
+ mockPopsicle.mock(url => {
+ const { urlFetcher } = require("../redux-test-utils").default;
+ return urlFetcher(url);
+ })
+ );
+
+ const mockChartUtils = withGlobalJquery(() => (ctx, cfg) => {
+ const chartCfg = { ctx, cfg, data: cfg.data, destroyed: false };
+ chartCfg.destroy = () => (chartCfg.destroyed = true);
+ chartCfg.getElementsAtXAxis = _evt => [{ _index: 0 }];
+ return chartCfg;
+ });
+
+ jest.mock("popsicle", () => mockBuildLibs);
+ jest.mock("chart.js", () => mockChartUtils);
+ jest.mock("chartjs-plugin-zoom", () => ({}));
+ });
+
+ afterAll(() => {
+ Object.defineProperty(HTMLElement.prototype, "offsetHeight", originalOffsetHeight);
+ Object.defineProperty(HTMLElement.prototype, "offsetWidth", originalOffsetWidth);
+ });
+
+ test("DataViewer: base operations (column selection, locking, sorting, moving to front, histograms,...", done => {
+ const { DataViewer, ReactDataViewer } = require("../../dtale/DataViewer");
+
+ const store = reduxUtils.createDtaleStore();
+ const body = document.getElementsByTagName("body")[0];
+ body.innerHTML += '';
+ body.innerHTML += '
';
+ const result = mount(
+
+
+ ,
+ {
+ attachTo: document.getElementById("content"),
+ }
+ );
+
+ setTimeout(() => {
+ result.update();
+ let dv = result.find(ReactDataViewer).instance();
+ dv.getData(dv.state.ids, true);
+ dv.getData(dv.state.ids, true);
+ dv = result.find(ReactDataViewer).instance();
+ t.deepEqual(
+ _.pick(dv.state, ["loading", "loadQueue"]),
+ { loading: true, loadQueue: [[0, 55]] },
+ "should update state"
+ );
+ dv.getData(dv.state.ids, true);
+ dv = result.find(ReactDataViewer).instance();
+ t.deepEqual(
+ _.pick(dv.state, ["loading", "loadQueue"]),
+ { loading: true, loadQueue: [[0, 55], [0, 55]] },
+ "should update state"
+ );
+ setTimeout(() => {
+ result.update();
+ dv = result.find(ReactDataViewer).instance();
+ t.deepEqual(
+ _.pick(dv.state, ["loading", "loadQueue"]),
+ { loading: false, loadQueue: [] },
+ "should clear state"
+ );
+ dv.getData(dv.state.ids);
+ dv.getData([0, 1, 2, 3]);
+ dv = result.find(ReactDataViewer).instance();
+ result.find(ReactDataViewer).setState({ query: "error", loadQueue: [], loading: false });
+ result.update();
+ dv = result.find(ReactDataViewer).instance();
+ dv.getData(dv.state.ids, true);
+ setTimeout(() => {
+ result.update();
+ t.equals(result.find(RemovableError).length, 1, "should display error");
+ done();
+ }, 400);
+ }, 400);
+ }, 600);
+ });
+});
diff --git a/static/dtale/DataViewer.jsx b/static/dtale/DataViewer.jsx
index cae0c9b3..ac1dd5ae 100644
--- a/static/dtale/DataViewer.jsx
+++ b/static/dtale/DataViewer.jsx
@@ -280,4 +280,4 @@ ReactDataViewer.propTypes = {
const ReduxDataViewer = connect()(ReactDataViewer);
-export { ReduxDataViewer as DataViewer };
+export { ReduxDataViewer as DataViewer, ReactDataViewer };
diff --git a/static/filter_console.jsx b/static/filter_console.jsx
deleted file mode 100644
index 9527c2fe..00000000
--- a/static/filter_console.jsx
+++ /dev/null
@@ -1,70 +0,0 @@
-const originalConsoleError = console.error;
-let patterns = [];
-
-// Patch console.error to ignore all errors that match the pattern
-// given.
-//
-// Usually, you will to call this only on dev builds:
-//
-// if (process.env.NODE_ENV == "dev") {
-// ignoreConsoleErrors(/foo/);
-// }
-//
-// This ensures that we don't filter any errors in production (helping
-// debugging and performance). React doesn't throw any warnings in
-// production builds anyway.
-function ignoreConsoleErrors(pattern) {
- patterns.push(pattern);
-
- // If we haven't patched console.error, patch it. This ensures that
- // users can call this function multiple times.
- if (originalConsoleError == console.error) {
- console.error = function(...args) {
- let message = null;
- // eslint-disable-next-line lodash/prefer-lodash-typecheck
- if (typeof args[0] === "string") {
- message = args[0];
- }
-
- // Skip the message if it matches.
- let shouldIgnore = false;
- patterns.forEach(pattern => {
- if (message && message.match(pattern)) {
- shouldIgnore = true;
- }
- });
-
- if (!shouldIgnore) {
- // Otherwise, continue to console.error as normal.
- originalConsoleError.apply(console, args);
- }
- };
- }
-}
-
-// Work around https://github.com/adazzle/react-data-grid/issues/418
-function ignoreDatagridWarnings() {
- const prefixes = [
- "Warning: Failed prop type: The prop `isScrolling` is marked as required ",
- "Warning: Failed prop type: Required prop ",
- "Warning: Failed prop type: Invalid prop `value` supplied to `Cell`.",
- "Warning: getDefaultProps is only used on classic React.createClass definitions.",
- "Warning: Failed prop type: You provided a `checked` prop to a form field without an `onChange` handler.",
- ];
- prefixes.forEach(prefix => {
- const pattern = new RegExp(`^${prefix}[\\s\\S]*created by (ReactDataGrid|ReactNodeGrid|ReactAtlasNodeGrid)`);
- ignoreConsoleErrors(pattern);
- });
- ignoreConsoleErrors(/^Warning: Cell: `ref` is not a prop./);
- ignoreConsoleErrors(/^Warning: Invalid argument supplied to oneOf, expected an instance of array./);
- ignoreConsoleErrors(/^Warning: `NaN` is an invalid value for the `width` css style property./);
- ignoreConsoleErrors(/Warning: getDefaultProps is only used on classic React.createClass definitions./);
- ignoreConsoleErrors(/Warning: Failed prop type: You provided a `checked` prop to a form field/);
-}
-
-function restoreConsoleError() {
- console.error = originalConsoleError;
- patterns = [];
-}
-
-export default { ignoreDatagridWarnings, ignoreConsoleErrors, restoreConsoleError };
diff --git a/test_env.js b/test_env.js
index 3cf6dc14..cdd2e0b1 100644
--- a/test_env.js
+++ b/test_env.js
@@ -3,12 +3,6 @@ import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
-// Provided that we're run *after* babel-register, we can load
-// filter_console, even though it's ES6.
-const filterConsole = require("./static/filter_console");
-filterConsole.default.ignoreDatagridWarnings();
-filterConsole.default.ignoreConsoleErrors(/This browser doesn't support the `onScroll` event/);
-
// required for react 16
global.requestAnimationFrame = function(callback) {
setTimeout(callback, 0);