Skip to content

Commit

Permalink
Support custom columns
Browse files Browse the repository at this point in the history
  • Loading branch information
openjck committed Mar 8, 2018
1 parent 54d1a09 commit 39c6b6e
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 31 deletions.
11 changes: 10 additions & 1 deletion manifests/usage.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,16 @@
"name": {
"title": "Top Add-ons",
"description": "The top 10 most popular add-ons.",
"type": "line"
"type": "table",
"columns": [
{
"name": "Add-on"
},
{
"name": "Usage",
"unit": "%"
}
]
}
}
}
Expand Down
124 changes: 94 additions & 30 deletions src/transpose.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ function propertyExists(obj, property) {
return property in obj;
}

function objectIsEmpty(obj) {
return Object.keys(obj).length === 0;
}

function processSource(error, body, manifest, callback) {
if (error) {
return callback({
Expand Down Expand Up @@ -80,35 +84,48 @@ function processSource(error, body, manifest, callback) {
if (!propertyExists(entry.metrics, metricName)) return;

const metricMeta = manifest.extraMetadata.metrics[metricName];
const metricType = metricMeta.type;

const metric = dataset.getMetric(
metricMeta.title || metricName,
metricMeta.description,
metricMeta.type,
metricType,
metricMeta.axes,
metricMeta.columns,
getSectionTitle(metricName),
);

const category = metric.getCategory(categoryName);

// If the source dataset doesn't specify any populations, create
// one "default" population.
let populations;
const multiplePopulations = typeof(entry.metrics[metricName]) === 'object';
if (multiplePopulations) {
populations = Object.keys(entry.metrics[metricName]);
} else {
populations = ['default'];
if (metricType === 'line') {

// If the source dataset doesn't specify any populations, create
// one "default" population.
let populations;
const multiplePopulations = typeof(entry.metrics[metricName]) === 'object';
if (multiplePopulations) {
populations = Object.keys(entry.metrics[metricName]);
} else {
populations = ['default'];
}

// For each population NAME
populations.forEach(populationName => {
const population = category.getPopulation(populationName);
const yValue = multiplePopulations ? entry.metrics[metricName][populationName] : entry.metrics[metricName];
const dataPoint = new DataPoint(entry.date, yValue);
population.addDataPoint(dataPoint);
}); // For each population NAME

} else if (metricType === 'table') {
// For each row NAME
Object.keys(entry.metrics[metricName]).map(rowName => {
const tableSnapshot = category.getTableSnapshot(entry.date);
const row = new Row(rowName, entry.metrics[metricName][rowName]);
tableSnapshot.addRow(row);
}); // For each row NAME
}

// For each population NAME
populations.forEach(populationName => {
const population = category.getPopulation(populationName);
const yValue = multiplePopulations ? entry.metrics[metricName][populationName] : entry.metrics[metricName];
const dataPoint = new DataPoint(entry.date, yValue);
population.addDataPoint(dataPoint);
}); // For each population NAME

}); // For each metric NAME

}); // For each entry OBJECT
Expand All @@ -130,9 +147,9 @@ class Dataset {
this.categoryNames = [];
}

getMetric(title, description, type, axes, section) {
getMetric(title, description, type, axes, columns, section) {
if (!propertyExists(this.metrics, title)) {
this.metrics[title] = new Metric(title, description, type, axes, section);
this.metrics[title] = new Metric(title, description, type, axes, columns, section);
}
return this.metrics[title];
}
Expand Down Expand Up @@ -170,11 +187,12 @@ class Dataset {
}

class Metric {
constructor(title, description, type, axes, section) {
constructor(title, description, type, axes, columns, section) {
this.title = title;
this.description = description;
this.type = type;
this.axes = axes;
this.columns = columns;
this.section = section;

this.categories = {};
Expand All @@ -189,19 +207,25 @@ class Metric {

render() {
const renderedCategories = {};

Object.keys(this.categories).forEach(categoryName => {
renderedCategories[categoryName] = this.categories[categoryName].render();
});

return {
const output = {
title: this.title,
description: this.description,
type: this.type,
axes: this.axes,
section: this.section,
categories: renderedCategories,
};

if (this.axes && !objectIsEmpty(this.axes)) {
output.axes = this.axes;
} else if (this.columns && !objectIsEmpty(this.columns)) {
output.columns = this.columns;
}

return output;
}
}

Expand All @@ -210,6 +234,7 @@ class Category {
this.name = name;

this.populations = {};
this.tableSnapshots = {};
}

getPopulation(populationName) {
Expand All @@ -219,16 +244,27 @@ class Category {
return this.populations[populationName];
}

render() {
const renderedPopulations = {};
getTableSnapshot(date) {
if (!propertyExists(this.tableSnapshots, date)) {
this.tableSnapshots[date] = new TableSnapshot();
}
return this.tableSnapshots[date];
}

Object.keys(this.populations).forEach(populationName => {
renderedPopulations[populationName] = this.populations[populationName].render();
});
render() {
const output = {};

return {
populations: renderedPopulations,
if (!objectIsEmpty(this.populations)) {
const renderedPopulations = {};
Object.keys(this.populations).forEach(populationName => {
renderedPopulations[populationName] = this.populations[populationName].render();
});
output.populations = renderedPopulations;
} else if (!objectIsEmpty(this.tableSnapshots)) {
output.dates = this.tableSnapshots;
}

return output;
}
}

Expand All @@ -248,6 +284,20 @@ class Population {
}
}

class TableSnapshot {
constructor() {
this.rows = [];
}

addRow(row) {
this.rows.push(row);
}

render() {
return this.rows.map(row => row.render());
}
}

class DataPoint {
constructor(x, y) {
this.x = x;
Expand All @@ -262,6 +312,20 @@ class DataPoint {
}
}

class Row {
constructor(name, value) {
this.name = name;
this.value = value;
}

render() {
return {
name: this.name,
value: this.value,
};
}
}

class Section {
constructor(key, title) {
this.key = key;
Expand Down

0 comments on commit 39c6b6e

Please sign in to comment.