Add chart save/load

This commit is contained in:
Alfred Melch 2019-08-06 14:03:05 +02:00
parent 2bcd62ebbe
commit 6308b16f34
8 changed files with 179 additions and 16 deletions

View File

@ -3924,6 +3924,11 @@
"escape-string-regexp": "1.0.5"
}
},
"file-drop-element": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/file-drop-element/-/file-drop-element-0.2.0.tgz",
"integrity": "sha512-BGDdaJ4U2Cz0qhv6YGLnuhVtKcN8fp7F/4dS7lGSL1Fbe8m4cbGk+8awwHW0xcFqutMojxGchMVuWYQpEpP/Qg=="
},
"file-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.0.0.tgz",

View File

@ -22,6 +22,7 @@
"dependencies": {
"benchmark": "^2.1.4",
"chart.js": "^2.8.0",
"file-drop-element": "^0.2.0",
"lodash": "^4.17.11",
"react": "^16.8.6",
"react-chartjs-2": "^2.7.6",

View File

@ -0,0 +1,63 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
file-drop {
position: relative;
box-sizing: border-box;
display: block;
padding: 10px;
background-color: rgba(245, 234, 174, 0.2);
overflow: hidden;
touch-action: none;
}
file-drop::after {
content: '';
position: absolute;
display: block;
left: 2px;
top: 2px;
right: 2px;
bottom: 2px;
border: 2px dashed #fff;
background-color: rgba(88, 116, 88, 0.2);
border-color: rgba(65, 129, 65, 0.5);
border-radius: 10px;
opacity: 0;
transform: scale(0.95);
transition: all 200ms ease-in;
transition-property: transform, opacity;
pointer-events: none;
}
.drop-valid::after {
opacity: 1;
transform: scale(1);
transition-timing-function: ease-out;
}
.drop-invalid::after {
background-color: rgba(255, 27, 27, 0.2);
border-color: rgba(255, 170, 170, 0.5);
opacity: 1;
transform: scale(1);
transition-timing-function: ease-out;
}
</style>
</head>
<body>
<header>Header <a href="../">Back</a></header>
<main>
<div>
<file-drop id="file-drop" accept="application/json"
>Drop config here</file-drop
>
</div>
<div><canvas id="myChart" width="600" height="400"></canvas></div>
</main>
<script src="./loadChart.js"></script>
</body>
</html>

View File

@ -12,6 +12,10 @@
<h1>Benchmarking</h1>
</header>
<main id="root"></main>
<footer>
Footer
<a href="./chart.html">Load previously saved chart</a>
</footer>
<script src="./bundle.js"></script>
</body>

View File

@ -2,6 +2,7 @@ import React from 'react'
import { Line, Bar } from 'react-chartjs-2'
import debounceRender from 'react-debounce-render'
import { downloadAsJson } from '../../../lib/json-download/index.js'
import { datasetTemplates, genOptions, beautifyLabels } from './chartOptions.js'
export class Chart extends React.Component {
@ -43,13 +44,20 @@ class WasmVsJsChart extends React.Component {
dataset.data = dataset.data.map(mean => 1000 / mean)
}
}
render() {
let data = JSON.parse(JSON.stringify(this.props.data)) // deep copy
let options = genOptions('Wasm vs. JavaScript', false, this.state.scaleY)
if (this.state.values === 'hz') this.convertDataToHz(data)
return (
<>
<Line height={400} width={400} data={data} options={options} />
<Line
ref={ref => (this.ref = ref)}
height={400}
width={400}
data={data}
options={options}
/>
<label>Scale Y-Axis</label>
<select
name="scaleY"
@ -69,6 +77,7 @@ class WasmVsJsChart extends React.Component {
<option value="mean">ms per operation (mean)</option>
<option value="hz">Operations per second (hz)</option>
</select>
<button onClick={() => saveChart(this.ref)}>Save chart</button>
</>
)
}
@ -103,20 +112,60 @@ function modifyDataArrays(data, exec, pre, after) {
}
}
const WasmStackChart = ({ data }) => {
modifyDataArrays(data, 'simplifyWASM', 'storeCoords', 'loadResult')
const options = genOptions('Wasm execution', true)
return <Bar height={400} width={400} data={data} options={options} />
class WasmStackChart extends React.Component {
render() {
const data = this.props.data
modifyDataArrays(data, 'simplifyWASM', 'storeCoords', 'loadResult')
const options = genOptions('Wasm execution', true)
return (
<>
<Bar
ref={ref => (this.ref = ref)}
height={400}
width={400}
data={data}
options={options}
/>
<button onClick={() => saveChart(this.ref)}>Save chart</button>
</>
)
}
}
const JsStackChart = ({ data }) => {
const options = genOptions('SimplifyJS execution', true)
modifyDataArrays(
data,
'origSimplifyWithTransformCase',
'transformToObjectFormCase',
'transformToArrayFormCase'
)
return <Bar height={400} width={400} data={data} options={options} />
class JsStackChart extends React.Component {
render() {
const data = this.props.data
const options = genOptions('SimplifyJS execution', true)
modifyDataArrays(
data,
'origSimplifyWithTransformCase',
'transformToObjectFormCase',
'transformToArrayFormCase'
)
return (
<>
<Bar
ref={ref => (this.ref = ref)}
height={400}
width={400}
data={data}
options={options}
/>
<button onClick={() => saveChart(this.ref)}>Save chart</button>
</>
)
}
}
export const DebouncedChart = debounceRender(Chart, 300)
/**
* Downloads the chart config as json
*/
function saveChart(chartRef) {
let myChart = chartRef.chartInstance.config
let config = JSON.stringify(myChart, (key, val) =>
key === '_meta' ? undefined : val
)
downloadAsJson(config, 'config.json')
}

View File

@ -0,0 +1,23 @@
import 'file-drop-element'
import Chart from 'chart.js'
const fileDrop = document.getElementById('file-drop')
const canvas = document.getElementById('myChart')
const ctx = canvas.getContext('2d')
async function readFile(file) {
return new Promise(resolve => {
let reader = new FileReader()
reader.readAsText(file)
reader.onload = function() {
resolve(this.result)
}
})
}
fileDrop.addEventListener('filedrop', e => {
readFile(e.files[0])
.then(JSON.parse)
.then(config => new Chart(ctx, config))
})

View File

@ -3,10 +3,13 @@ const CopyPlugin = require('copy-webpack-plugin')
const path = require('path')
module.exports = {
entry: './src/index.js',
entry: {
bundle: './src/index.js',
loadChart: './src/loadChart.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
filename: '[name].js'
},
module: {
// Suppress warnings and errors logged by benchmark.js when bundled using webpack.

View File

@ -0,0 +1,15 @@
/*
Taken from: https://stackoverflow.com/questions/19721439/download-json-object-as-a-file-from-browser
*/
export function downloadAsJson(exportObj, exportName) {
if (typeof exportObj !== 'string') exportObj = JSON.stringify(exportObj)
var dataStr =
'data:application/json;charset=utf-8,' + encodeURIComponent(exportObj)
var downloadAnchorNode = document.createElement('a')
downloadAnchorNode.setAttribute('href', dataStr)
downloadAnchorNode.setAttribute('download', exportName)
document.body.appendChild(downloadAnchorNode) // required for firefox
downloadAnchorNode.click()
downloadAnchorNode.remove()
}