├── .gitignore ├── LICENSE ├── README.md ├── bin └── hyperchart ├── components └── chart.js ├── constants.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Matthew Conlen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hyperchart 2 | charts for hyperterm. built on [hyperterm-window](https://github.com/mathisonian/hyperterm-window) 3 | 4 | ![hyperchart](https://cloud.githubusercontent.com/assets/1074773/17677176/9e821b4c-62ff-11e6-926a-6c0d8a914118.gif) 5 | 6 | ## install 7 | 8 | ``` 9 | $ npm install -g hyperchart 10 | ``` 11 | 12 | to get the command line tool and then add `hyperchart` to your `plugins` array in `~/.hyperterm.js`. You'll see a notification popup once the plugin installation happens successfully (give it a few seconds for `npm install` to finish) 13 | 14 | 15 | ## usage 16 | 17 | ``` 18 | hyperchart -- 19 | ``` 20 | 21 | Valid chart types are: `line`, `scatter`. 22 | 23 | 24 | ### data formatting: 25 | 26 | Data is passed directly to [victory react components](https://formidable.com/open-source/victory/). In general it should be json like: 27 | 28 | ```json 29 | [{"x": "val", "y": "val"}, ...] 30 | ``` 31 | -------------------------------------------------------------------------------- /bin/hyperchart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const OUTPUT_HEADER = require('../constants').OUTPUT_HEADER; 4 | const allowedTypes = ['line', 'scatter']; 5 | const argv = require('yargs').argv; 6 | const temp = require('temp'); 7 | 8 | var type; 9 | Object.keys(argv).forEach((key) => { 10 | if (argv[key] && allowedTypes.indexOf(key) > -1) { 11 | type = key; 12 | delete argv[key]; 13 | } 14 | }); 15 | 16 | if (!type) { 17 | console.error('Must provide a valid type. Valid types are: ' + (allowedTypes.join(', ')) + '.'); 18 | return; 19 | } 20 | 21 | const stream = temp.createWriteStream(); 22 | const cat = require('posix-cat')(argv); 23 | 24 | process.stdin.pipe(cat).pipe(stream); 25 | cat.on('end', function () { 26 | stream.end(); 27 | process.stdout.write(OUTPUT_HEADER + '\n' + JSON.stringify({ path: stream.path, type: type })); 28 | process.exit(); 29 | }); 30 | -------------------------------------------------------------------------------- /components/chart.js: -------------------------------------------------------------------------------- 1 | 2 | const Victory = require('victory'); 3 | const Axis = require('victory').VictoryAxis; 4 | const Chart = Victory.VictoryChart; 5 | 6 | const chartMap = { 7 | line: Victory.VictoryLine, 8 | scatter: Victory.VictoryScatter 9 | }; 10 | 11 | const getStyles = (props) => { 12 | switch (props.type) { 13 | case 'line': 14 | return { 15 | stroke: props.foregroundColor 16 | }; 17 | case 'scatter': 18 | return { 19 | fill: props.foregroundColor 20 | }; 21 | } 22 | } 23 | 24 | const getAxisStyles = (props) => { 25 | return { 26 | axis: {stroke: props.foregroundColor}, 27 | // grid: {stroke: props.backgroundColor}, 28 | ticks: {size: 0}, 29 | tickLabels: {fill: props.foregroundColor}, 30 | axisLabel: {fill: props.foregroundColor} 31 | }; 32 | }; 33 | 34 | module.exports = (React) => { 35 | return (props) => { 36 | const Component = chartMap[props.type]; 37 | const xAxis = React.createElement(Axis, {style: getAxisStyles(props)}); 38 | const yAxis = React.createElement(Axis, {style: getAxisStyles(props), dependentAxis: true}); 39 | const Viz = React.createElement(Component, {data: props.data, style: {data: getStyles(props)}}); 40 | if (props.expanded) { 41 | return React.createElement(Chart, {style: { 42 | axis: { 43 | axis: {stroke: "black"}, 44 | grid: {strokeWidth: 2}, 45 | ticks: {stroke: "red", size: 4}, 46 | tickLabels: {fontSize: 12}, 47 | axisLabel: {fontsize: 16} 48 | } 49 | }}, [xAxis, yAxis, Viz]); 50 | } 51 | return Viz; 52 | }; 53 | }; 54 | -------------------------------------------------------------------------------- /constants.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | OUTPUT_HEADER: 'HYPERTERM_OUTPUT~~~~~' 4 | }; 5 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | const OUTPUT_HEADER = require('./constants').OUTPUT_HEADER; 3 | const fs = require('fs'); 4 | 5 | exports.reduceUI = (state, action) => { 6 | switch (action.type) { 7 | case 'SET_CHART': 8 | return state.set('chart', action.chart); 9 | } 10 | return state; 11 | }; 12 | 13 | exports.mapTermsState = (state, map) => { 14 | return Object.assign(map, { 15 | chart: state.ui.chart 16 | }); 17 | }; 18 | 19 | exports.mapTermsDispatch = (dispatch, map) => { 20 | return Object.assign(map, { 21 | clearChart: () => { 22 | dispatch({ 23 | type: 'SET_CHART', 24 | chart: null 25 | }); 26 | } 27 | }) 28 | }; 29 | 30 | exports.getTermProps = (uid, parentProps, props) => { 31 | return Object.assign(props, { 32 | chart: parentProps.chart, 33 | clearChart: parentProps.clearChart 34 | }); 35 | }; 36 | 37 | exports.middleware = (store) => (next) => (action) => { 38 | if (!action) { 39 | return; 40 | } 41 | if (action.type === 'SESSION_ADD_DATA') { 42 | const { data } = action; 43 | if (data.trim().startsWith(OUTPUT_HEADER)) { 44 | const metadata = JSON.parse(data.replace(OUTPUT_HEADER, '')); 45 | let jsonData = null; 46 | fs.readFile(metadata.path, 'utf8', function (err, filedata) { 47 | if (err) { 48 | // send error to console 49 | console.log(err); 50 | return; 51 | }; 52 | jsonData = JSON.parse(filedata); 53 | store.dispatch({ 54 | type: 'SET_CHART', 55 | chart: { 56 | type: metadata.type, 57 | data: jsonData 58 | } 59 | }); 60 | }); 61 | } else { 62 | return next(action); 63 | } 64 | } else { 65 | return next(action); 66 | } 67 | }; 68 | 69 | exports.decorateTerm = (Term, { React, notify }) => { 70 | try { 71 | require('react'); 72 | } catch(e) { 73 | var Module = require('module'); 74 | var originalRequire = Module.prototype.require; 75 | Module.prototype.require = function (path) { 76 | if (path === 'react') { 77 | return React; 78 | } 79 | return originalRequire.apply(this, arguments); 80 | }; 81 | } 82 | 83 | const Chart = require('./components/chart')(React); 84 | const Window = require('hyperterm-window'); 85 | 86 | return class extends React.Component { 87 | render () { 88 | const { backgroundColor, foregroundColor } = this.props; 89 | const children = [React.createElement(Term, Object.assign({}, this.props, { key: 'term' }))]; 90 | if (this.props.chart) { 91 | const chart = React.createElement(Chart, Object.assign({}, this.props.chart, { 92 | key: 'hyperchart', 93 | colors: this.props.colors, 94 | backgroundColor: backgroundColor, 95 | foregroundColor: foregroundColor 96 | })); 97 | const hyperwindow = React.createElement(Window, Object.assign({}, this.props, {key: 'window', onClose: this.props.clearChart}), chart); 98 | children.push(hyperwindow); 99 | } 100 | return React.createElement('div', {style: {width: '100%', height: '100%', position: 'relative'}}, children); 101 | } 102 | } 103 | }; 104 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperchart", 3 | "version": "1.0.1", 4 | "description": "Charts in hyperterm", 5 | "main": "index.js", 6 | "bin": { 7 | "hyperchart": "bin/hyperchart" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/mathisonian/hyperchart.git" 15 | }, 16 | "keywords": [ 17 | "hyperterm", 18 | "data", 19 | "data", 20 | "viz", 21 | "chart", 22 | "viz" 23 | ], 24 | "author": "Matthew Conlen ", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/mathisonian/hyperchart/issues" 28 | }, 29 | "homepage": "https://github.com/mathisonian/hyperchart#readme", 30 | "dependencies": { 31 | "hyperterm-window": "^1.0.1", 32 | "posix-cat": "^1.1.1", 33 | "temp": "^0.8.3", 34 | "victory": "^0.10.4" 35 | } 36 | } 37 | --------------------------------------------------------------------------------