Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
typpo committed Mar 4, 2019
0 parents commit 39da974
Show file tree
Hide file tree
Showing 7 changed files with 2,982 additions and 0 deletions.
130 changes: 130 additions & 0 deletions .gitignore
@@ -0,0 +1,130 @@
venv

### Vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~


### OSX ###
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/


### Node ###
# Logs
logs
*.log
npm-debug.log*

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules

35 changes: 35 additions & 0 deletions charts.js
@@ -0,0 +1,35 @@
const DEFAULT_COLORS = {
blue: 'rgba(54, 162, 235, 0.5)',
orange: 'rgba(255, 159, 64, 0.5)',
purple: 'rgba(153, 102, 255, 0.5)',
red: 'rgba(255, 99, 132, 0.5)',
yellow: 'rgba(255, 205, 86, 0.5)',
green: 'rgba(75, 192, 192, 0.5)',
grey: 'rgba(201, 203, 207, 0.5)',
};

const DEFAULT_COLOR_WHEEL = Object.values(DEFAULT_COLORS);

function addBackgroundColors(chart) {
if (chart.data && chart.data.datasets && Array.isArray(chart.data.datasets)) {
chart.data.datasets.forEach((dataset, idx) => {
if (!dataset.backgroundColor) {
if (chart.type === 'pie' || chart.type === 'doughnut') {
dataset.backgroundColor = dataset.data.map((_, idx) => {
// Return a color for each value.
return DEFAULT_COLOR_WHEEL[idx % DEFAULT_COLOR_WHEEL.length];
});
} else {
// Return a color for each dataset.
dataset.backgroundColor = DEFAULT_COLOR_WHEEL[idx % DEFAULT_COLOR_WHEEL.length];
}
}
});
}
}

module.exports = {
DEFAULT_COLORS,
DEFAULT_COLOR_WHEEL,
addBackgroundColors,
};
128 changes: 128 additions & 0 deletions index.js
@@ -0,0 +1,128 @@
const path = require('path');

const ChartjsNode = require('chartjs-node');
const express = require('express');
const expressNunjucks = require('express-nunjucks');
const winston = require('winston');
const { toJson } = require('really-relaxed-json');

const { addBackgroundColors, DEFAULT_COLOR_WHEEL } = require('./charts');

const logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ timestamp: true, colorize: true }),
],
});

const app = express();

const isDev = app.get('env') === 'development';

app.set('views', `${__dirname}/templates`);
app.use(express.static('public'));

expressNunjucks(app, {
watch: isDev,
noCache: isDev,
});

app.get('/', (req, res) => {
res.render('index');
});

app.get('/robots.txt', (req, res) => {
res.sendFile(path.join(__dirname, './templates/robots.txt'));
});

app.get('/chart', (req, res) => {
if (!req.query.c) {
res.send('You are missing variable `c`');
return;
}

let height = 300;
let width = 500;
if (req.h || req.height) {
const heightNum = parseInt(req.h || req.height, 10);
if (!isNaN(heightNum)) {
height = heightNum;
}
}
if (req.w || req.width) {
const heightNum = parseInt(req.w || req.width, 10);
if (!isNaN(widthNum)) {
width = widthNum;
}
}

const chart = JSON.parse(toJson(req.query.c));

if (chart.type === 'donut') {
// Fix spelling...
chart.type === 'doughnut';
}

if (typeof chart.options === 'undefined') {
// Implement default options
chart.options = {};
if (chart.type === 'bar' || chart.type === 'line') {
chart.options = {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
},
}],
},
};
addBackgroundColors(chart);
} else if (chart.type === 'radar') {
addBackgroundColors(chart);
} else if (chart.type === 'pie' || chart.type === 'doughnut') {
addBackgroundColors(chart);
}
}

console.log(JSON.stringify(chart))

const chartNode = new ChartjsNode(width, height);
chartNode.drawChart(chart).then(() => {
return chartNode.getImageBuffer('image/png');
}).then(buf => {
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': buf.length,
});
res.end(buf);
chartNode.destroy();
});
});

if (!isDev) {
function gracefulShutdown() {
logger.info('Received kill signal, shutting down gracefully.');
server.close(() => {
logger.info('Closed out remaining connections.');
process.exit();
});

// if after
setTimeout(() => {
logger.error('Could not close connections in time, forcefully shutting down');
process.exit();
}, 10 * 1000);
}

// listen for TERM signal .e.g. kill
process.on('SIGTERM', gracefulShutdown);

// listen for INT signal e.g. Ctrl-C
process.on('SIGINT', gracefulShutdown);
}

const port = process.env.PORT || 3400;
const server = app.listen(port);
logger.info('NODE_ENV:', process.env.NODE_ENV);
logger.info('Running on port', port);

module.exports = app;
15 changes: 15 additions & 0 deletions package.json
@@ -0,0 +1,15 @@
{
"name": "staticchart",
"version": "1.0.0",
"main": "index.js",
"license": "None",
"dependencies": {
"chart.js": "^2.7.3",
"chartjs-node": "^1.7.1",
"express": "^4.16.4",
"express-nunjucks": "^2.2.3",
"nunjucks": "^3.1.7",
"really-relaxed-json": "^0.2.24",
"winston": "^2.3.1"
}
}

0 comments on commit 39da974

Please sign in to comment.