Explorar el Código

Add sample data and prepare skeleton of component.

rongmz hace 5 años
padre
commit
53da727271
Se han modificado 8 ficheros con 10220 adiciones y 33 borrados
  1. 9972 0
      example/public/20200814
  2. 82 7
      example/src/App.js
  3. 86 0
      example/src/index.css
  4. 6 11
      package-lock.json
  5. 0 1
      package.json
  6. 68 4
      src/index.js
  7. 1 1
      src/index.test.js
  8. 5 9
      src/styles.module.css

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 9972 - 0
example/public/20200814


+ 82 - 7
example/src/App.js

@@ -1,10 +1,85 @@
-import React from 'react'
+import React from 'react';
+import StockHeatmap from '@rongmz/react-stock-heatmap';
+import '@rongmz/react-stock-heatmap/dist/index.css';
 
-import { ExampleComponent } from '@rongmz/react-stock-heatmap'
-import '@rongmz/react-stock-heatmap/dist/index.css'
 
-const App = () => {
-  return <ExampleComponent text="Create React Library Example 😄" />
-}
+export default () => {
+
+  const [loading, setLoading] = React.useState(true);
+  const progressRef = React.useRef(null);
+  const heatmapRef = React.useRef(null);
+  const [windowDim, setWindowDim] = React.useState([0, 0]);
+
+  // ------------ Load data -------------
+  React.useEffect(() => {
+    setLoading(true);
+    fetch('http://localhost:3000/20200814').then(async ({ body, headers }) => {
+      const reader = body.getReader();
+      // Step 2: get total length
+      const contentLength = +headers.get('Content-Length');
+      // Step 3: read the data
+      let receivedLength = 0; // received that many bytes at the moment
+      let chunks = []; // array of received binary chunks (comprises the body)
+      while (true) {
+        const { done, value } = await reader.read();
+        if (done) {
+          break;
+        }
+        chunks.push(value);
+        receivedLength += value.length;
+        // console.log(`Received ${receivedLength} of ${contentLength} %=${100 * (receivedLength / contentLength)}`)
+        if (progressRef.current !== null) {
+          progressRef.current.innerHTML = ` Downloading ${(100 * receivedLength / contentLength).toFixed(1)}% ...`
+        }
+      }
+      // Step 4: concatenate chunks into single Uint8Array
+      let chunksAll = new Uint8Array(receivedLength); // (4.1)
+      let position = 0;
+      for (let chunk of chunks) {
+        chunksAll.set(chunk, position); // (4.2)
+        position += chunk.length;
+      }
+      // Step 5: decode into a string
+      let result = new TextDecoder("utf-8").decode(chunksAll);
+      // setdata
+      if (heatmapRef.current !== null) {
+        heatmapRef.current.setData(
+          result.split('\n')
+            .filter(v => v.trim() !== '')
+            .map(v => JSON.parse(v))
+        );
+      }
+      setLoading(false);
+    })
+  }, []);
+  // ------------ Load data -------------
+
+  // ---------- window update ------------
+  React.useEffect(() => {
+    const updateFn = () => {
+      setWindowDim([
+        window.innerWidth,
+        window.innerHeight
+      ]);
+    }
+    updateFn();
+    window.addEventListener('resize', updateFn);
+    return () => window.removeEventListener('resize', updateFn);
+  }, []);
+  // ---------- window update ------------
 
-export default App
+  return (
+    <React.Fragment>
+
+      {loading &&
+        <div className="loadingIndicator">
+          <div className="loadingSpinner">
+            <div className="loader">Loading...</div>
+          </div>
+          <div ref={progressRef}> Downloading 0% ...</div>
+        </div>}
+
+      <StockHeatmap ref={heatmapRef} width={windowDim[0]} height={windowDim[1]} />
+    </React.Fragment>
+  )
+}

+ 86 - 0
example/src/index.css

@@ -12,3 +12,89 @@ code {
   font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
     monospace;
 }
+
+.loader {
+  font-size: 10px;
+  margin: 0px auto;
+  text-indent: -9999em;
+  width: 2em;
+  height: 2em;
+  border-radius: 50%;
+  background: #000000;
+  background: -moz-linear-gradient(left, #000000 10%, rgba(255, 255, 255, 0) 42%);
+  background: -webkit-linear-gradient(left, #000000 10%, rgba(255, 255, 255, 0) 42%);
+  background: -o-linear-gradient(left, #000000 10%, rgba(255, 255, 255, 0) 42%);
+  background: -ms-linear-gradient(left, #000000 10%, rgba(255, 255, 255, 0) 42%);
+  background: linear-gradient(to right, #000000 10%, rgba(255, 255, 255, 0) 42%);
+  position: relative;
+  -webkit-animation: load3 1.4s infinite linear;
+  animation: load3 1.4s infinite linear;
+  -webkit-transform: translateZ(0);
+  -ms-transform: translateZ(0);
+  transform: translateZ(0);
+}
+
+.loader:before {
+  width: 50%;
+  height: 50%;
+  background: #000000;
+  border-radius: 100% 0 0 0;
+  position: absolute;
+  top: 0;
+  left: 0;
+  content: '';
+}
+
+.loader:after {
+  background: #ffffff;
+  width: 75%;
+  height: 75%;
+  border-radius: 50%;
+  content: '';
+  margin: auto;
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+
+@-webkit-keyframes load3 {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+@keyframes load3 {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+
+.loadingIndicator {
+  position: fixed;
+  padding: 10px;
+  display: flex;
+  flex-direction: row;
+  background: #fff;
+  margin: 10px;
+  box-shadow: 0 0 11px -2px #000;
+  border-radius: 2em;
+  right: 0;
+}
+
+.loadingSpinner {
+  margin-right: 10px;
+}

+ 6 - 11
package-lock.json

@@ -1649,11 +1649,6 @@
         "picomatch": "^2.2.2"
       }
     },
-    "@rongmz/simple-event-emitter": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@rongmz/simple-event-emitter/-/simple-event-emitter-1.0.3.tgz",
-      "integrity": "sha512-ct54RmaqHtTJWtRqeMG/VDxi2DwnyF8Hv0F9iBIKqymZqIAzvvLcLsnP7+x0Jji4N4oVR/Hl3v5bBZ9oKc3D2w=="
-    },
     "@svgr/babel-plugin-add-jsx-attribute": {
       "version": "5.4.0",
       "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz",
@@ -8041,12 +8036,6 @@
       "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
       "dev": true
     },
-    "immer": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/immer/-/immer-1.10.0.tgz",
-      "integrity": "sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg==",
-      "dev": true
-    },
     "import-cwd": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz",
@@ -13065,6 +13054,12 @@
           "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
           "dev": true
         },
+        "immer": {
+          "version": "1.10.0",
+          "resolved": "https://registry.npmjs.org/immer/-/immer-1.10.0.tgz",
+          "integrity": "sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg==",
+          "dev": true
+        },
         "inquirer": {
           "version": "7.0.4",
           "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz",

+ 0 - 1
package.json

@@ -67,7 +67,6 @@
     "dist"
   ],
   "dependencies": {
-    "@rongmz/simple-event-emitter": "^1.0.3",
     "d3-array": "^2.7.1",
     "d3-color": "^2.0.0",
     "d3-format": "^2.0.0",

+ 68 - 4
src/index.js

@@ -1,6 +1,70 @@
-import React from 'react'
-import styles from './styles.module.css'
+import React from 'react';
+import styles from './styles.module.css';
+// import PropTypes from 'prop-types';
 
-export const ExampleComponent = ({ text }) => {
-  return <div className={styles.test}>Example Component: {text}</div>
+/**
+ * Stock Heatmap
+ * @author Rounak Saha
+ * © Copyright 2020, Rounak Saha
+ */
+export default class StockHeatmap extends React.Component {
+
+  canvasRef = React.createRef();
+  data = [];
+
+  shouldComponentUpdate(nextProps, nextState) {
+    const shouldUpdate = this.props.width !== nextProps.width
+      || this.props.height !== nextProps.height;
+    if (shouldUpdate) updateHeatmapDimensions();
+    return shouldUpdate;
+  }
+
+
+  /**
+   * This function will be called if there is any dimension change on heatmap
+   */
+  updateHeatmapDimensions() {
+
+  }
+
+  /**
+   * This method will be called after an update of internal data is performed.
+   */
+  updateHeatmap() {
+
+  }
+
+  /**
+   * Set Data for the Heatmap to generate
+   * @param {any[]} data The data to set
+   */
+  setData(data) {
+    console.log('setdata called=', data);
+    if (data && data.length > 0) {
+      this.data = data;
+      this.updateHeatmap();
+    }
+  }
+
+  /**
+   * Add as extra data to existing data array.
+   * @param {any} data 
+   */
+  addData(data) {
+    if (typeof (data) === 'object') {
+      this.data.push(data);
+      this.updateHeatmap();
+    }
+  }
+
+  /**
+   * Render Function
+   */
+  render() {
+    const { width, height } = this.props;
+    console.log('heatmap rendered', width, height, this.data);
+    return (
+      <canvas ref={this.canvasRef} width={width || 300} height={height || 150} className={styles.mapCanvas}></canvas>
+    );
+  }
 }

+ 1 - 1
src/index.test.js

@@ -1,4 +1,4 @@
-import { ExampleComponent } from '.'
+import ExampleComponent from '.'
 
 describe('ExampleComponent', () => {
   it('is truthy', () => {

+ 5 - 9
src/styles.module.css

@@ -1,9 +1,5 @@
-/* add css module styles here (optional) */
-
-.test {
-  margin: 2em;
-  padding: 0.5em;
-  border: 2px solid #000;
-  font-size: 2em;
-  text-align: center;
-}
+.mapCanvas {
+  display: block;
+  width: 100%;
+  height: 100%;
+}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio