diff --git a/modules/charts.mjs b/modules/charts.mjs new file mode 100644 index 0000000..ce23ad1 --- /dev/null +++ b/modules/charts.mjs @@ -0,0 +1,30 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; +import {JSDOM} from "jsdom"; + +const dom = new JSDOM(``); + +export function makeBarChart(data, x, y) { + + // see https://stackoverflow.com/questions/74573576/how-to-use-observable-plot-in-nodejs + // see https://github.com/observablehq/plot/discussions/847?sort=top + + let plot = Plot.plot({ + x: { + tickFormat: d3.format(",.1c"), + label: "" + }, + y: { + label: "" + }, + style: { + fontSize: "14px", + }, + document: dom.window.document, + marks: [ + Plot.barY(data, {x: x, y: y, fill: "grey"}), + Plot.ruleY([0]) + ] + }); + return plot.outerHTML; +} diff --git a/modules/data.js b/modules/data.js index 04c246d..083e27a 100644 --- a/modules/data.js +++ b/modules/data.js @@ -2,6 +2,9 @@ const fetch = require('node-fetch'); const querystring = require('querystring'); const { response } = require('express'); +let charts; +import('./charts.mjs').then(c => {charts = c;}) + const API_KEY = process.env.API_KEY; function makeURL(endpoint, parameters, aggregations) { @@ -249,6 +252,13 @@ function getKeyStats(callback) { "extended_stats": { "field": "createdat" } + }, + "keys_by_year": { + "date_histogram": { + "field": "createdat", + "interval": "1y", + "time_zone": "America/New_York" + } } }; const url = makeURL('key', params, aggs); @@ -263,9 +273,24 @@ function getKeyStats(callback) { start: results.aggregations.date_stats.min_as_string, end: results.aggregations.date_stats.max_as_string }, + charts: { + keys_by_year: "" + } } }; + let data = []; + let databucket = results.aggregations.keys_by_year.buckets; + databucket.forEach(d => { + let group = { + year: parseInt(d.key_as_string.slice(0,4)), + count: d.doc_count + }; + data.push(group); + }); + + output.keys.charts.keys_by_year = charts.makeBarChart(data, "year", "count"); + callback(null, output); }); } diff --git a/package.json b/package.json index be779fb..2def05d 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,16 @@ "start": "node ./bin/www" }, "dependencies": { + "@observablehq/plot": "^0.6.1", "async": "^3.2.0", "cookie-parser": "~1.4.4", + "d3": "^7.8.0", "debug": "~2.6.9", "dotenv": "^8.2.0", "express": "~4.16.1", "hbs": "^4.1.1", "http-errors": "~1.6.3", + "jsdom": "^20.0.3", "morgan": "~1.9.1", "node-fetch": "^2.6.0" } diff --git a/routes/index.js b/routes/index.js index afe2e1d..06a0a31 100644 --- a/routes/index.js +++ b/routes/index.js @@ -79,6 +79,7 @@ router.get('/', function(req, res, next) { data.keys.count_as_string = data.keys.count.toLocaleString('en'); data.keys.statsdates = results['keyStats']['keys']['statsdates']; data.keys.statsdates.start_short = data.keys.statsdates.start.substr(0, 10); + data.keys.chart_by_year = results['keyStats']['keys']['charts']['keys_by_year']; // calculate the age of the data // freshness = number of hours old diff --git a/views/production.hbs b/views/production.hbs index 1f5d9d1..4d4a8e9 100644 --- a/views/production.hbs +++ b/views/production.hbs @@ -33,7 +33,11 @@

{{apistats.keys.count_as_string}} keys have been issued since {{apistats.keys.statsdates.start_short}}.

The newest key was cut at precisely {{apistats.keys.statsdates.end}}.

+ +
+

Key Count by Year

+

{{{apistats.keys.chart_by_year}}}