Commit 398cd5d8 authored by Pithon Kabiro's avatar Pithon Kabiro
Browse files

Merge branch 'wip_select-sensors-dropdown-list-8' into 'master'

Update logic for drop-down list

Refactor the logic for the drop-down lists into new module files

See merge request !23
parents 33c36fee f7b471cf
Pipeline #5170 passed with stage
in 31 seconds
......@@ -17,10 +17,9 @@ import {
extractPropertiesFromFormattedDatastreamMetadata,
} from "./src_modules/fetchedDataProcessing.mjs";
import {
formatSensorThingsApiResponseForLineOrColumnChart,
drawLineChartHighcharts,
} from "./src_modules/chartLine.mjs";
import { formatSensorThingsApiResponseForLineOrColumnChart } from "./src_modules/chartHelpers.mjs";
import { drawLineChartHighcharts } from "./src_modules/chartLine.mjs";
import { drawColumnChartHighcharts } from "./src_modules/chartColumn.mjs";
......@@ -50,12 +49,13 @@ import {
getAbbreviationsForSelectedOptionsFromAllDropDownLists,
} from "./src_modules/dropDownListHelpers.mjs";
import {
drawHeatmapBasedOnSelectedOptions,
drawScatterPlotFromChartSelection,
drawLineChartBasedOnSelectedAggregationOptions,
drawColumnChartBasedOnSelectedAggregationOptions,
} from "./src_modules/dropDownListProcessing.mjs";
import { drawColumnChartBasedOnSelectedAggregationOptions } from "./src_modules/dropDownListChartColumn.mjs";
import { drawHeatmapBasedOnSelectedOptions } from "./src_modules/dropDownListChartHeatmap.mjs";
import { drawLineChartBasedOnSelectedAggregationOptions } from "./src_modules/dropDownListChartLine.mjs";
import { drawScatterPlotFromChartSelection } from "./src_modules/dropDownListChartScatterPlot.mjs";
/**
* Use the `vanillaDropDown` library to style the buildings & data points drop down list
......@@ -193,7 +193,7 @@ const drawChartUsingSelectedOptions = async function () {
)
: selectedBuildingsDataPointsSamplingRateAbbrevNestedArr;
// Check if we have dT (temperature difference)
// Check if we have dT (temperature difference), if so, extract these options
const selectedBuildingsDataPointsSamplingRateAbbrevTempDiffArr =
checkIfSelectedOptionsContainTemperatureDifference(
selectedBuildingsDataPointsSamplingRateAbbrevNestedArr
......
......@@ -354,10 +354,42 @@ const extractUniqueCalendarMonthsFromCalendarDates = function (
return [...uniqueCalendarMonths];
};
/**
* Format a computed aggregation result to make it suitable for a chart. Currently, only line and column charts are supported
* @param {Array} calendarDatesMonthsStrArr An array of unique calendar dates strings (in "YYYY-MM-DD" fromat) or unique calendar months strings (in "YYYY-MM" format)
* @param {Array} aggregatedValuesArr An array of aggregated values
* @returns {Array} An array of formatted aggregation values suitable for use in a column chart
*/
const formatAggregationResultForChart = function (
calendarDatesMonthsStrArr,
aggregatedValuesArr
) {
if (!calendarDatesMonthsStrArr || !aggregatedValuesArr) return;
// Create an array of Unix timestamp strings
const timestampsArr = calendarDatesMonthsStrArr.map((calendarStr) =>
new Date(calendarStr).getTime()
);
// Combine timestamp and value pairs
// The timestamps array and values array have same lengths, use one for looping
if (timestampsArr.length !== aggregatedValuesArr.length) {
throw new Error(
"The timestamps array and aggregated values array have different lengths"
);
} else {
return timestampsArr.map((timestamp, i) => [
timestamp,
aggregatedValuesArr[i],
]);
}
};
export {
extractObservationsWithinDatesInterval,
extractObservationValuesWithinDatesInterval,
extractObservationValuesWithinMonthInterval,
extractUniqueCalendarDatesFromTimestamp,
extractUniqueCalendarMonthsFromCalendarDates,
formatAggregationResultForChart,
};
......@@ -9,31 +9,6 @@ import {
createTooltipDateString,
} from "./chartHelpers.mjs";
/**
* Format a computed aggregation result to make it suitable for a column chart
* @param {Array} calendarDatesMonthsStrArr An array of unique calendar dates strings (in "YYYY-MM-DD" fromat) or unique calendar months strings (in "YYYY-MM" format)
* @param {Array} aggregatedValuesArr An array of aggregated values
* @returns {Array} An array of formatted aggregation values suitable for use in a column chart
*/
const formatAggregationResultForColumnChart = function (
calendarDatesMonthsStrArr,
aggregatedValuesArr
) {
if (!calendarDatesMonthsStrArr || !aggregatedValuesArr) return;
// Create an array of Unix timestamp strings
const timestampsArr = calendarDatesMonthsStrArr.map((calendarStr) =>
new Date(calendarStr).getTime()
);
// Combine timestamp and value pairs
// The timestamps array and values array have same lengths, use one for looping
return timestampsArr.map((timestamp, i) => [
timestamp,
aggregatedValuesArr[i],
]);
};
/**
* Creates an options object for each series drawn in a column chart
* @param {Array} formattedAggregatedResultForColumnChart An array of formatted aggregated result array(s) from one or more datastreams
......@@ -96,12 +71,12 @@ const createYAxisTitleTextColumnChart = function (
/**
* Draw a column chart using Highcharts library
* @param {Array} formattedAggResultArraysForColumnChart An array made up of formatted aggregated result array(s) suitable for use in a column chart
* @param {Array} formattedObsArraysForColumnChart An array made up of formatted observation array(s) suitable for use in a column chart. The observations may either be raw or aggregated
* @param {Object} extractedFormattedDatastreamProperties An object that contains arrays of formatted Datastream properties
* @returns {undefined} undefined
*/
const drawColumnChartHighcharts = function (
formattedAggResultArraysForColumnChart,
formattedObsArraysForColumnChart,
extractedFormattedDatastreamProperties
) {
// Formatted datastream properties
......@@ -136,7 +111,7 @@ const drawColumnChartHighcharts = function (
// Create the array of series options object(s)
const seriesOptionsArr = createSeriesOptionsForColumnChart(
formattedAggResultArraysForColumnChart,
formattedObsArraysForColumnChart,
buildingIdsPhenomenonNamesArr
);
......@@ -213,4 +188,4 @@ const drawColumnChartHighcharts = function (
});
};
export { formatAggregationResultForColumnChart, drawColumnChartHighcharts };
export { drawColumnChartHighcharts };
......@@ -57,7 +57,7 @@ const calculateMinMaxValuesForHeatmapColorAxis = function (
/**
* Draw a heatmap using Highcharts library
* @param {Array} formattedObsArrayForHeatmap Response from SensorThings API formatted for use in a heatmap
* @param {Array} formattedObsArrayForHeatmap Response from SensorThings API formatted for use in a heatmap. Currently, only raw observations are supported, i.e. no aggregation
* @param {Object} extractedFormattedDatastreamProperties An object that contains arrays of formatted Datastream properties
* @returns {undefined} undefined
*/
......
......@@ -177,6 +177,21 @@ const checkForAndDeleteUniqueObservationsFromLargerArray = function (
}
};
/**
* Format the response from SensorThings API to make it suitable for use in a line chart or column chart
* @param {Array} obsArray Array of observations (timestamp + value) that is response from SensorThings API
* @returns {Array} Array of formatted observations suitable for use in a line chart
*/
const formatSensorThingsApiResponseForLineOrColumnChart = function (obsArray) {
if (!obsArray) return;
return obsArray.map((result) => {
const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp
const valueObs = result[1];
return [timestampObs, valueObs];
});
};
/**
* Convert a hexadecimal color code obtained from the Highcharts object (`Highcharts.getOptions().colors`) to its equivalent RGB color code
* @param {String} hexCode Input hex color code
......@@ -406,6 +421,7 @@ const removeTransparencyFromColor = function (rgbaColor) {
export {
chartExportOptions,
checkForAndDeleteUniqueObservationsFromLargerArray,
formatSensorThingsApiResponseForLineOrColumnChart,
createCombinedTextDelimitedByAmpersand,
createCombinedTextDelimitedByComma,
extractSamplingRateFromDatastreamName,
......
......@@ -7,30 +7,6 @@ import {
createTooltipDateString,
} from "./chartHelpers.mjs";
/**
* Format the response from SensorThings API to make it suitable for use in a line chart or column chart
* @param {Array} obsArray Array of observations (timestamp + value) that is response from SensorThings API
* @returns {Array} Array of formatted observations suitable for use in a line chart
*/
const formatSensorThingsApiResponseForLineOrColumnChart = function (obsArray) {
if (!obsArray) return;
return obsArray.map((result) => {
const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp
const valueObs = result[1];
return [timestampObs, valueObs];
});
};
/**
* Concatenates metadata properties to create a string for either the title or subtitle of a line chart
* @param {Array} phenomenonNamesArr An array of phenomenon name strings
* @returns {String} A string made up of combined phenomenon names
*/
const createCombinedTextForLineChartTitles = function (phenomenonNamesArr) {
return phenomenonNamesArr.join(", ");
};
/**
* Creates an options object for each series drawn in the line chart
* @param {Array} formattedObsArraysForLineChart An array of formatted observation array(s) from one or more datastreams
......@@ -42,10 +18,10 @@ const createSeriesOptionsForLineChart = function (
buildingIdsPhenomenonNamesArr
) {
// An array of colors, in hexadecimal format, provided by the global Highcharts object
const seriesColors = Highcharts.getOptions().colors;
const seriesColorsArr = Highcharts.getOptions().colors;
// Create a copy of the colors array
const seriesColorsArr = [...seriesColors];
// Create a local copy of the colors array
const seriesColorsForLineChartArr = [...seriesColorsArr];
// Create an array of seriesOptions objects
// Assumes that the observation array of arrays and building IDs + phenomenon names array are of equal length
......@@ -62,7 +38,7 @@ const createSeriesOptionsForLineChart = function (
return {
name: `${buildingIdsPhenomenonNamesArr[i]}`,
data: formattedObsArray,
color: seriesColorsArr[i],
color: seriesColorsForLineChartArr[i],
turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
};
});
......@@ -71,7 +47,7 @@ const createSeriesOptionsForLineChart = function (
/**
* Draw a line chart using Highcharts library
* @param {Array} formattedObsArraysForLineChart An array made up of formatted observation array(s) suitable for use in a line chart
* @param {Array} formattedObsArraysForLineChart An array made up of formatted observation array(s) suitable for use in a line chart. The observations may either be raw or aggregated
* @param {Object} extractedFormattedDatastreamPropertiesArr An object that contains arrays of formatted Datastream properties
* @returns {undefined} undefined
*/
......@@ -171,7 +147,4 @@ const drawLineChartHighcharts = function (
});
};
export {
formatSensorThingsApiResponseForLineOrColumnChart,
drawLineChartHighcharts,
};
export { drawLineChartHighcharts };
......@@ -36,20 +36,18 @@ const formatSensorThingsApiResponseForScatterPlot = function (
obsArrayOne,
obsArrayTwo
) {
// When our observation arrays have DIFFERENT lengths
if (obsArrayOne.length !== obsArrayTwo.length) {
const [obsArrayOneFinal, obsArrayTwoFinal] =
checkForAndDeleteUniqueObservationsFromLargerArray(
obsArrayOne,
obsArrayTwo
);
return createCombinedObservationValues(obsArrayOneFinal, obsArrayTwoFinal);
}
// When our observation arrays already have SAME lengths
else {
return createCombinedObservationValues(obsArrayOne, obsArrayTwo);
}
// Check if our observation arrays have equal lengths,
// remove the unique observations, if necessary
const [obsArrayOneFinal, obsArrayTwoFinal] =
obsArrayOne.length !== obsArrayTwo.length
? checkForAndDeleteUniqueObservationsFromLargerArray(
obsArrayOne,
obsArrayTwo
)
: [obsArrayOne, obsArrayTwo];
// Create the combined observations array
return createCombinedObservationValues(obsArrayOneFinal, obsArrayTwoFinal);
};
/**
......@@ -138,14 +136,14 @@ const createSeriesOptionsForScatterPlot = function (
// An array of colors, in hexadecimal format, provided by the global Highcharts object
const highchartsColorsArr = Highcharts.getOptions().colors;
// Create a reversed copy of the colors array
const highchartsColorsReversedArr = [...highchartsColorsArr].reverse();
// Create a local copy of the colors array
const highchartsColorsForScatterPlotArr = [...highchartsColorsArr];
// Opacity value for symbol
const SERIES_SYMBOL_COLOR_OPACITY = ".3";
// Create array of colors in RGBA format
const seriesColors = highchartsColorsReversedArr.map(
const seriesColorsArr = highchartsColorsForScatterPlotArr.map(
(hexColorCode) =>
`rgba(${convertHexColorToRGBColor(
hexColorCode
......@@ -171,7 +169,7 @@ const createSeriesOptionsForScatterPlot = function (
return {
name: `${phenomenonNamesYAxisArr[i]}, ${phenomenonNameXAxis}`,
data: formattedObsArray,
color: seriesColors[i],
color: seriesColorsArr[i],
};
});
}
......@@ -209,12 +207,12 @@ const getYAxisUnitOfMeasurementSymbol = function (seriesName) {
/**
* Draw a scatter plot using Highcharts library
* @param {Array} formattedObsArrayForSeriesOnePlusSeriesTwo Response from SensorThings API formatted for use in a scatter plot
* @param {Array} formattedObsArraysForScatterPlot Response from SensorThings API formatted for use in a scatter plot. Currently, only raw observations are supported, i.e. no aggregation
* @param {Object} extractedFormattedDatastreamProperties An object that contains arrays of formatted Datastream properties
* @returns {undefined} undefined
*/
const drawScatterPlotHighcharts = function (
formattedObsArrayForSeriesOnePlusSeriesTwo,
formattedObsArraysForScatterPlot,
extractedFormattedDatastreamProperties
) {
// Arrays of datastream properties
......@@ -227,7 +225,7 @@ const drawScatterPlotHighcharts = function (
// Create the array of series options object(s)
const seriesOptionsArr = createSeriesOptionsForScatterPlot(
formattedObsArrayForSeriesOnePlusSeriesTwo,
formattedObsArraysForScatterPlot,
phenomenonNamesArr
);
......
"use strict";
import {
extractUniqueCalendarMonthsFromCalendarDates,
formatAggregationResultForChart,
} from "./aggregateHelpers.mjs";
import { calculateAverageOfObservationValuesWithinInterval } from "./aggregate.mjs";
import { extractPropertiesFromFormattedDatastreamMetadata } from "./fetchedDataProcessing.mjs";
/**
* Calculate the daily average of observations and format these aggregated observations
*
* @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
* @param {Array} observationsNestedArr An array made up of sub-array(s) of observations
* @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
* @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
* @returns {Array} An array whose first element is the formatted aggregated (daily average) observations. The second element is an object made up of extracted & formatted datastream properties
*/
const calculateAndFormatDailyAverageObservations = function (
uniqueCalendarDatesNestedArr,
observationsNestedArr,
selectedSamplingRateAbbrev,
formattedMetadataNestedArr
) {
// Calculate AVERAGE / DAILY of values of observations
const observationsAverageDailyNestedArr =
calculateAverageOfObservationValuesWithinInterval(
observationsNestedArr,
selectedSamplingRateAbbrev,
uniqueCalendarDatesNestedArr,
"daily"
);
// Format the observations
const formattedObservationsAverageDailyNestedArr =
observationsAverageDailyNestedArr.map((obsAverageDailyArr, i) =>
formatAggregationResultForChart(
uniqueCalendarDatesNestedArr[i],
obsAverageDailyArr
)
);
// Extract the formatted metadata properties
const extractedFormattedDatastreamProperties =
extractPropertiesFromFormattedDatastreamMetadata(
formattedMetadataNestedArr,
true,
"daily",
"average"
);
return [
formattedObservationsAverageDailyNestedArr,
extractedFormattedDatastreamProperties,
];
};
/**
* Calculate the monthly average of observations and format these aggregated observations
*
* @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
* @param {Array} observationsNestedArr An array made up of sub-array(s) of observations
* @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
* @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
* @returns {Array} An array whose first element is the formatted aggregated (monthly average) observations. The second element is an object made up of extracted & formatted datastream properties
*/
const calculateAndFormatMonthlyAverageObservations = function (
uniqueCalendarDatesNestedArr,
observationsNestedArr,
selectedSamplingRateAbbrev,
formattedMetadataNestedArr
) {
// Unique calendar months
const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
(uniqueCalendarDatesArr) =>
extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
);
// Calculate AVERAGE / MONTHLY of values of observations
const observationsAverageMonthlyNestedArr =
calculateAverageOfObservationValuesWithinInterval(
observationsNestedArr,
selectedSamplingRateAbbrev,
uniqueCalendarMonthsNestedArr,
"monthly"
);
// Format the observations
const formattedObservationsAverageMonthlyNestedArr =
observationsAverageMonthlyNestedArr.map((obsAverageMonthlyArr, i) =>
formatAggregationResultForChart(
uniqueCalendarMonthsNestedArr[i],
obsAverageMonthlyArr
)
);
// Extract the formatted metadata properties
const extractedFormattedDatastreamProperties =
extractPropertiesFromFormattedDatastreamMetadata(
formattedMetadataNestedArr,
true,
"monthly",
"average"
);
return [
formattedObservationsAverageMonthlyNestedArr,
extractedFormattedDatastreamProperties,
];
};
export {
calculateAndFormatDailyAverageObservations,
calculateAndFormatMonthlyAverageObservations,
};
"use strict";
import {
extractUniqueCalendarMonthsFromCalendarDates,
formatAggregationResultForChart,
} from "./aggregateHelpers.mjs";
import { calculateMaximumObservationValuesWithinInterval } from "./aggregate.mjs";
import { extractPropertiesFromFormattedDatastreamMetadata } from "./fetchedDataProcessing.mjs";
/**
* Calculate the daily maximum of observations and format these aggregated observations
*
* @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
* @param {Array} observationsNestedArr An array made up of sub-array(s) of observations
* @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
* @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
* @returns {Array} An array whose first element is the formatted aggregated (daily maximum) observations. The second element is an object made up of extracted & formatted datastream properties
*/
const calculateAndFormatDailyMaximumObservations = function (
uniqueCalendarDatesNestedArr,
observationsNestedArr,
selectedSamplingRateAbbrev,
formattedMetadataNestedArr
) {
// Calculate MAXIMUM / DAILY of values of observations
const observationsMaximumDailyNestedArr =
calculateMaximumObservationValuesWithinInterval(
observationsNestedArr,
selectedSamplingRateAbbrev,
uniqueCalendarDatesNestedArr,
"daily"
);
// Format the observations
const formattedObservationsMaximumDailyNestedArr =
observationsMaximumDailyNestedArr.map((obsMinDailyArr, i) =>
formatAggregationResultForChart(
uniqueCalendarDatesNestedArr[i],
obsMinDailyArr
)
);
// Extract the formatted metadata properties
const extractedFormattedDatastreamProperties =
extractPropertiesFromFormattedDatastreamMetadata(
formattedMetadataNestedArr,
true,
"daily",
"maximum"
);
return [
formattedObservationsMaximumDailyNestedArr,
extractedFormattedDatastreamProperties,
];
};
/**
* Calculate the monthly maximum of observations and format these aggregated observations
*
* @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
* @param {Array} observationsNestedArr An array made up of sub-array(s) of observations
* @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
* @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
* @returns {Array} An array whose first element is the formatted aggregated (monthly maximum) observations. The second element is an object made up of extracted & formatted datastream properties
*/
const calculateAndFormatMonthlyMaximumObservations = function (
uniqueCalendarDatesNestedArr,
observationsNestedArr,
selectedSamplingRateAbbrev,
formattedMetadataNestedArr
) {
// Unique calendar months
const uniqueCalendarMonthsNestedArr = uniqueCalendarDatesNestedArr.map(
(uniqueCalendarDatesArr) =>
extractUniqueCalendarMonthsFromCalendarDates(uniqueCalendarDatesArr)
);
// Calculate MAXIMUM / MONTHLY of values of observations
const observationsMaximumMonthlyNestedArr =
calculateMaximumObservationValuesWithinInterval(
observationsNestedArr,
selectedSamplingRateAbbrev,
uniqueCalendarMonthsNestedArr,
"monthly"
);
// Format the observations
const formattedObservationsMaximumMonthlyNestedArr =
observationsMaximumMonthlyNestedArr.map((obsMaxMonthlyArr, i) =>
formatAggregationResultForChart(
uniqueCalendarMonthsNestedArr[i],
obsMaxMonthlyArr
)
);
// Extract the formatted metadata properties
const extractedFormattedDatastreamProperties =
extractPropertiesFromFormattedDatastreamMetadata(
formattedMetadataNestedArr,
true,
"monthly",
"maximum"
);
return [
formattedObservationsMaximumMonthlyNestedArr,
extractedFormattedDatastreamProperties,
];
};
export {
calculateAndFormatDailyMaximumObservations,
calculateAndFormatMonthlyMaximumObservations,
};
"use strict";
import {
extractUniqueCalendarMonthsFromCalendarDates,
formatAggregationResultForChart,
} from "./aggregateHelpers.mjs";
import { calculateMinimumObservationValuesWithinInterval } from "./aggregate.mjs";
import { extractPropertiesFromFormattedDatastreamMetadata } from "./fetchedDataProcessing.mjs";
/**
* Calculate the daily minimum of observations and format these aggregated observations
*
* @param {Array} uniqueCalendarDatesNestedArr An array made up of sub-array(s) of unique calendar date(s) string(s)
* @param {Array} observationsNestedArr An array made up of sub-array(s) of observations
* @param {String} selectedSamplingRateAbbrev A string representing the abbreviated form of the selected sampling rate option
* @param {Array} formattedMetadataNestedArr An array of sub-arrays of formatted metadata properties
* @returns {Array} An array whose first element is the formatted aggregated (daily minimum) observations. The second element is an object made up of extracted & formatted datastream properties
*/
const calculateAndFormatDailyMinimumObservations = function (
uniqueCalendarDatesNestedArr,
observationsNestedArr,
selectedSamplingRateAbbrev,
formattedMetadataNestedArr
) {