Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Charts port to ESM #496

Merged
merged 24 commits into from
Mar 31, 2019
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
fa89713
Add d3 as a dependency
tlwr May 30, 2017
281d558
Add hex density chart
tlwr May 30, 2017
6cdc7d3
Hex density: split radius into draw & pack radii
tlwr May 30, 2017
dc642be
Hex plot: add edge drawing & changing colour opts
tlwr May 30, 2017
b4188db
Hexagon density: allow dense plotting of hexagons
tlwr May 31, 2017
1c87707
Add heatmap chart operation
tlwr Jun 5, 2017
5944568
Change margins in hex density chart
tlwr Jun 5, 2017
247e9bf
Add "HTML to Text" operation
tlwr Jun 6, 2017
49ea532
Tweak extent of hex density charts
tlwr Jun 6, 2017
39ab600
Add scatter plot operation
tlwr Jun 6, 2017
6784a1c
Add Series chart operation
tlwr Jun 20, 2017
5bb8eb2
Merge branch 'master' into module-charts
mattnotmitt Feb 22, 2019
da2d567
Ported heatmap and hex density chart ops
mattnotmitt Feb 23, 2019
4ae8756
Ported final two chart operations
mattnotmitt Mar 10, 2019
f8874fc
Actually made operations work (and made the module 8MB)
mattnotmitt Mar 10, 2019
0019a4e
Found a different dom implementation that removes 6MB
mattnotmitt Mar 10, 2019
6501454
Cleanup
mattnotmitt Mar 10, 2019
ca6d472
Update nodom
mattnotmitt Mar 10, 2019
fd7fd9c
Remove jsdom from dependencies
mattnotmitt Mar 11, 2019
66c0425
Merge branch 'master' into module-charts
mattnotmitt Mar 11, 2019
cd22985
Fix categories JSON issue
mattnotmitt Mar 11, 2019
768fef5
Changed version of nodom to actually functioning fork
mattnotmitt Mar 14, 2019
3ad5f88
Wrote some tests, fixed imports for node
mattnotmitt Mar 14, 2019
b3d92b0
Updated nodom dependency to upstream
mattnotmitt Mar 19, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
465 changes: 367 additions & 98 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
"crypto-api": "^0.8.3",
"crypto-js": "^3.1.9-1",
"ctph.js": "0.0.5",
"d3": "^4.9.1",
"d3-hexbin": "^0.2.2",
"diff": "^3.5.0",
"es6-promisify": "^6.0.1",
"escodegen": "^1.11.0",
Expand Down Expand Up @@ -118,6 +120,7 @@
"ngeohash": "^0.6.3",
"node-forge": "^0.7.6",
"node-md6": "^0.1.0",
"nodom": "^2.1.0",
"notepack.io": "^2.2.0",
"nwmatcher": "^1.4.4",
"otp": "^0.1.3",
Expand Down
1 change: 1 addition & 0 deletions src/core/Utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,7 @@ class Utils {
"Comma": ",",
"Semi-colon": ";",
"Colon": ":",
"Tab": "\t",
"Line feed": "\n",
"CRLF": "\r\n",
"Forward slash": "/",
Expand Down
4 changes: 4 additions & 0 deletions src/core/config/Categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@
"Remove EXIF",
"Extract EXIF",
"Split Colour Channels",
"Hex Density chart",
"Scatter chart",
"Series chart",
"Heatmap chart",
"Rotate Image",
"Resize Image",
"Blur Image",
Expand Down
175 changes: 175 additions & 0 deletions src/core/lib/Charts.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/**
* @author tlwr [toby@toby.codes] - Original
* @author Matt C [me@mitt.dev] - Conversion to new format
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/

import OperationError from "../errors/OperationError";

/**
* @constant
* @default
*/
export const RECORD_DELIMITER_OPTIONS = ["Line feed", "CRLF"];


/**
* @constant
* @default
*/
export const FIELD_DELIMITER_OPTIONS = ["Space", "Comma", "Semi-colon", "Colon", "Tab"];


/**
* Default from colour
*
* @constant
* @default
*/
export const COLOURS = {
min: "white",
max: "black"
};


/**
* Gets values from input for a plot.
*
* @param {string} input
* @param {string} recordDelimiter
* @param {string} fieldDelimiter
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
* @returns {Object[]}
*/
export function getValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded, length) {
let headings;
const values = [];

input
.split(recordDelimiter)
.forEach((row, rowIndex) => {
const split = row.split(fieldDelimiter);
if (split.length !== length) throw new OperationError(`Each row must have length ${length}.`);

if (columnHeadingsAreIncluded && rowIndex === 0) {
headings = split;
} else {
values.push(split);
}
});
return { headings, values};
}


/**
* Gets values from input for a scatter plot.
*
* @param {string} input
* @param {string} recordDelimiter
* @param {string} fieldDelimiter
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
* @returns {Object[]}
*/
export function getScatterValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
let { headings, values } = getValues(
input,
recordDelimiter, fieldDelimiter,
columnHeadingsAreIncluded,
2
);

if (headings) {
headings = {x: headings[0], y: headings[1]};
}

values = values.map(row => {
const x = parseFloat(row[0], 10),
y = parseFloat(row[1], 10);

if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");

return [x, y];
});

return { headings, values };
}

/**
* Gets values from input for a scatter plot with colour from the third column.
*
* @param {string} input
* @param {string} recordDelimiter
* @param {string} fieldDelimiter
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
* @returns {Object[]}
*/
export function getScatterValuesWithColour(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
let { headings, values } = getValues(
input,
recordDelimiter, fieldDelimiter,
columnHeadingsAreIncluded,
3
);

if (headings) {
headings = {x: headings[0], y: headings[1]};
}

values = values.map(row => {
const x = parseFloat(row[0], 10),
y = parseFloat(row[1], 10),
colour = row[2];

if (Number.isNaN(x)) throw new OperationError("Values must be numbers in base 10.");
if (Number.isNaN(y)) throw new OperationError("Values must be numbers in base 10.");

return [x, y, colour];
});

return { headings, values };
}

/**
* Gets values from input for a time series plot.
*
* @param {string} input
* @param {string} recordDelimiter
* @param {string} fieldDelimiter
* @param {boolean} columnHeadingsAreIncluded - whether we should skip the first record
* @returns {Object[]}
*/
export function getSeriesValues(input, recordDelimiter, fieldDelimiter, columnHeadingsAreIncluded) {
const { values } = getValues(
input,
recordDelimiter, fieldDelimiter,
false,
3
);

let xValues = new Set();
const series = {};

values.forEach(row => {
const serie = row[0],
xVal = row[1],
val = parseFloat(row[2], 10);

if (Number.isNaN(val)) throw new OperationError("Values must be numbers in base 10.");

xValues.add(xVal);
if (typeof series[serie] === "undefined") series[serie] = {};
series[serie][xVal] = val;
});

xValues = new Array(...xValues);

const seriesList = [];
for (const seriesName in series) {
const serie = series[seriesName];
seriesList.push({name: seriesName, data: serie});
}

return { xValues, series: seriesList };
}
Loading