Commit 4c983cf6 authored by Pithon Kabiro's avatar Pithon Kabiro
Browse files

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

Update logic for drop-down list

Improve processing logic for drop-down list (draw the appropriate 
chart based on selected options)

See merge request !16
parents 59f58680 35dc06f4
......@@ -69,7 +69,6 @@
Custom JS -->
<script defer type="module" src="js/appCesium.js"></script>
<script defer type="module" src="js/appChart.js"></script>
<script defer type="module" src="js/dropDownList.js"></script>
</head>
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
......@@ -131,6 +130,21 @@
<label for="droneMode">Drone View</label>
</div>
<br /> -->
<div id="drop-down--chart-type-parent">
<span><strong>Chart type</strong></span>
<div class="nowrap">
<!-- We need the `multiple` attribute for the dropdowns even if
we do not need to support multiple selections. This seems to
be a quirk of the `vanillaSelectBox` library -->
<select id="drop-down--chart-type" multiple>
<option>Column</option>
<option>Line</option>
<option>Heatmap</option>
<option>Scatter Plot</option>
</select>
</div>
</div>
<br />
<div id="drop-down--bldg-data-point-parent">
<span><strong>Building(s), Data Point(s)</strong></span>
<div class="nowrap">
......@@ -140,6 +154,9 @@
size="5"
>
<!-- Note: The values of the option elements have to be unique -->
<optgroup label="Other">
<option>Außentemp</option>
</optgroup>
<optgroup label="Bau 101">
<option>101/VL</option>
<option>101/RL</option>
......@@ -174,9 +191,6 @@
<option>225/Energie</option>
<option>225/Energie_VERBR</option>
</optgroup>
<optgroup label="Other">
<option>Außentemp</option>
</optgroup>
</select>
</div>
</div>
......@@ -216,21 +230,6 @@
</div>
</div>
<br />
<div id="drop-down--chart-type-parent">
<span><strong>Chart type</strong></span>
<div class="nowrap">
<!-- We need the `multiple` attribute for the dropdowns even if
we do not need to support multiple selections. This seems to
be a quirk of the `vanillaSelectBox` library -->
<select id="drop-down--chart-type" multiple>
<option>Column</option>
<option>Line</option>
<option>Heatmap</option>
<option>Scatter Plot</option>
</select>
</div>
</div>
<br />
<button id="btn-draw-chart">Draw Chart</button>
<!-- <span><strong>Display Options</strong></span>
<div class="nowrap">
......
This diff is collapsed.
......@@ -7,127 +7,139 @@ import { getMetadataPlusObservationsFromSingleOrMultipleDatastreams } from "./fe
import { extractPhenomenonNameFromDatastreamName } from "./fetchedDataProcessing.mjs";
/**
* Calculate the temperature difference, dT, between Vorlauf temperature [VL] and Rücklauf temperature [RL] (i.e., dT = VL - RL)
* Calculate the temperature difference, dT, between Vorlauf temperature [VL] and
* Rücklauf temperature [RL] (i.e., dT = VL - RL). In addition, create synthetic metadata
* for the temperature difference
* @async
* @param {String} baseUrl Base URL of the STA server
* @param {Object} urlParams The URL parameters to be sent together with the GET request
* @param {String} buildingId The building ID as a string
* @param {String} samplingRate The sampling rate as a string
* @returns {Promise} A promise that contains an array (that is made up of a temperature difference array and a metadata object) when fulfilled
* @param {Array} buildingSamplingRateNestedArr A N*1 array (where N >= 1) containing a nested array of buildings & sampling rates as strings, i.e. [["101", "15min"]] or [["101", "15min"], ["102", "60min"]] or [["101", "15min"], ["102", "60min"], ["225", "60min"]], etc
* @returns {Promise} A promise that contains a 1*2 array (the first element is an array that contans N Observations arrays; and the second element is an array of N Datastream metadata objects) when fulfilled
*/
export const calculateVorlaufMinusRuecklaufTemperature = async function (
baseUrl,
urlParams,
buildingId,
samplingRate
buildingSamplingRateNestedArr
) {
try {
const bldgSensorSamplingRateNestedArr = [
[buildingId, "vl", samplingRate],
[buildingId, "rl", samplingRate],
];
const BUILDING_ID = buildingId;
const SAMPLING_RATE = samplingRate;
const observationsPlusMetadata =
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
baseUrl,
urlParams,
bldgSensorSamplingRateNestedArr
// Arrays to store our results
const combinedObservationsArr = [];
const combinedMetadataArr = [];
const buildingDataPointSamplingRateNestedTwiceArr =
buildingSamplingRateNestedArr.map((bldgSmplngRate) => {
// The building ID is the first element, sampling rate is second element
return [
[bldgSmplngRate[0], "vl", bldgSmplngRate[1]],
[bldgSmplngRate[0], "rl", bldgSmplngRate[1]],
];
});
// Note: We have to use a for/of loop here due to the asynchronous nature of our code
for (const bldgDataPtSamplingRateNestedArr of buildingDataPointSamplingRateNestedTwiceArr) {
// Use the first element of the nested array to extract building ID + sampling rate
// Note: we skip the second element
const [buildingId, , samplingRate] = bldgDataPtSamplingRateNestedArr[0];
const BUILDING_ID = buildingId;
const SAMPLING_RATE = samplingRate;
const observationsPlusMetadata =
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
baseUrl,
urlParams,
bldgDataPtSamplingRateNestedArr
);
// Extract Vorlauf temperature, Ruecklauf temperature and metadata
const [
[vorlaufTemperatureObsArr, ruecklaufTemperatureObsArr],
[metadataVorlauf, metadataRuecklauf],
] = observationsPlusMetadata;
// Compare the lengths of the observations arrays for VL and RL,
// delete the unique observation(s), if necessary
const [vorlaufTemperatureObsFinalArr, ruecklaufTemperatureObsFinalArr] =
vorlaufTemperatureObsArr.length === ruecklaufTemperatureObsArr.length
? [vorlaufTemperatureObsArr, ruecklaufTemperatureObsArr]
: checkForAndDeleteUniqueObservationsFromLargerArray(
vorlaufTemperatureObsArr,
ruecklaufTemperatureObsArr
);
// Extract the temperature values
const vorlaufTemperatureValues = vorlaufTemperatureObsFinalArr.map(
(vlTempObs) => vlTempObs[1]
);
const ruecklaufTemperatureValues = ruecklaufTemperatureObsFinalArr.map(
(rlTempObs) => rlTempObs[1]
);
// Extract Vorlauf temperature, Ruecklauf temperature and metadata
const [
[vorlaufTemperatureObsArr, ruecklaufTemperatureObsArr],
[metadataVorlauf, metadataRuecklauf],
] = observationsPlusMetadata;
// Compare the lengths of the observations arrays for VL and RL,
// delete the unique observation(s), if necessary
const [vorlaufTemperatureObsFinalArr, ruecklaufTemperatureObsFinalArr] =
vorlaufTemperatureObsArr.length === ruecklaufTemperatureObsArr.length
? [vorlaufTemperatureObsArr, ruecklaufTemperatureObsArr]
: checkForAndDeleteUniqueObservationsFromLargerArray(
vorlaufTemperatureObsArr,
ruecklaufTemperatureObsArr
);
// Extract the temperature values
const vorlaufTemperatureValues = vorlaufTemperatureObsFinalArr.map(
(vlTempObs) => vlTempObs[1]
);
const ruecklaufTemperatureValues = ruecklaufTemperatureObsFinalArr.map(
(rlTempObs) => rlTempObs[1]
);
// The arrays have equal length, we need only use one of them for looping
// Resulting array contains the following pairs (timestamp + dT)
const vorlaufMinusRuecklaufTemperatureObs = vorlaufTemperatureObsArr.map(
(vlTempObs, i) => {
// Use timestamp from VL, since is equal to that of RL
const timestamp = vlTempObs[0];
// Case 1: One of the observation values is `null`,
// no need to calculate temperature difference
if (
vorlaufTemperatureValues[i] === null ||
ruecklaufTemperatureValues[i] === null
) {
return [timestamp, null];
// The arrays have equal length, we need only use one of them for looping
// Resulting array contains the following pairs (timestamp + dT)
const vorlaufMinusRuecklaufTemperatureObs = vorlaufTemperatureObsArr.map(
(vlTempObs, i) => {
// Use timestamp from VL, since is equal to that of RL
const timestamp = vlTempObs[0];
// Case 1: One of the observation values is `null`,
// no need to calculate temperature difference
if (
vorlaufTemperatureValues[i] === null ||
ruecklaufTemperatureValues[i] === null
) {
return [timestamp, null];
}
// Case 2: Neither of the observation values is `null`,
// calculate temperature difference
return [
timestamp,
vorlaufTemperatureValues[i] - ruecklaufTemperatureValues[i],
];
}
);
// Case 2: Neither of the observation values is `null`,
// calculate temperature difference
return [
timestamp,
vorlaufTemperatureValues[i] - ruecklaufTemperatureValues[i],
];
}
);
// From Vorlauf metadata, extract `name` and `unitOfMeasurement`
const {
name: datastreamNameVorlauf,
unitOfMeasurement: unitOfMeasurementVorlauf,
} = metadataVorlauf;
// From Ruecklauf metadata, extract `name`
const { name: datastreamNameRuecklauf } = metadataRuecklauf;
// Extract the phenomenon names from the Datastream names
const phenomenonNameVorlauf = extractPhenomenonNameFromDatastreamName(
datastreamNameVorlauf
);
const phenomenonNameRuecklauf = extractPhenomenonNameFromDatastreamName(
datastreamNameRuecklauf
);
// Create our custom datastream description text
// The resulting datastream description string has two `temperature` substrings;
// replace the first occurence with an empty string
const descriptionTempDifference =
`Computed dT: ${phenomenonNameVorlauf} minus ${phenomenonNameRuecklauf}`.replace(
"temperature",
""
// From Vorlauf metadata, extract `name` and `unitOfMeasurement`
const {
name: datastreamNameVorlauf,
unitOfMeasurement: unitOfMeasurementVorlauf,
} = metadataVorlauf;
// From Ruecklauf metadata, extract `name`
const { name: datastreamNameRuecklauf } = metadataRuecklauf;
// Extract the phenomenon names from the Datastream names
const phenomenonNameVorlauf = extractPhenomenonNameFromDatastreamName(
datastreamNameVorlauf
);
const phenomenonNameRuecklauf = extractPhenomenonNameFromDatastreamName(
datastreamNameRuecklauf
);
// Create our custom datastream name text
const nameTempDifference = `BOSCH_${BUILDING_ID} / dT Temperature difference (VL-RL) DS:${SAMPLING_RATE}`;
// The datastream object that we return needs to have these property names
const description = descriptionTempDifference;
const name = nameTempDifference;
const unitOfMeasurement = unitOfMeasurementVorlauf;
return [
vorlaufMinusRuecklaufTemperatureObs,
{
description,
name,
unitOfMeasurement,
},
];
// Create our custom datastream description text
// The resulting datastream description string has two `temperature` substrings;
// replace the first occurence with an empty string
const descriptionTempDifference =
`Computed dT: ${phenomenonNameVorlauf} minus ${phenomenonNameRuecklauf}`.replace(
"temperature",
""
);
// Create our custom datastream name text
const nameTempDifference = `BOSCH_${BUILDING_ID} / dT Temperature difference (VL-RL) DS:${SAMPLING_RATE}`;
// The datastream object that we return needs to have these property names
const description = descriptionTempDifference;
const name = nameTempDifference;
const unitOfMeasurement = unitOfMeasurementVorlauf;
// Add the observations and metadata to our arrays
combinedObservationsArr.push(vorlaufMinusRuecklaufTemperatureObs);
combinedMetadataArr.push({ description, name, unitOfMeasurement });
}
return [combinedObservationsArr, combinedMetadataArr];
} catch (err) {
console.error(err);
}
......
"use strict";
import {
BASE_URL,
QUERY_PARAMS_COMBINED,
} from "./src_modules/baseUrlPlusQueryParams.mjs";
import { getMetadataPlusObservationsFromSingleOrMultipleDatastreams } from "./src_modules/fetchData.mjs";
import {
formatDatastreamMetadataForChart,
extractPropertiesFromFormattedDatastreamMetadata,
} from "./src_modules/fetchedDataProcessing.mjs";
import {
formatSensorThingsApiResponseForLineOrColumnChart,
drawLineChartHighcharts,
} from "./src_modules/chartLine.mjs";
import {
formatSensorThingsApiResponseForHeatMap,
drawHeatMapHighcharts,
} from "./src_modules/chartHeatmap.mjs";
import {
showLoadingSpinner,
hideLoadingSpinner,
} from "./src_modules/loadingIndicator.mjs";
import { vanillaSelectBox } from "./thirdparty/vanillaSelectBox.mjs";
/**
* Use the `vanillaDropDown` library to style the first level drop down list
*
* @returns {undefined}
*/
const styleLevelOneDropDown = function () {
// Create our dropdown list using `vanillaSelectBox`; supports the selection of multiple options
new vanillaSelectBox("#drop-down--bldg-data-point", {
"disableSelectAll": true,
"maxSelect": 5,
"placeHolder": "--Select--",
"search": false,
});
};
/**
* Use the `vanillaDropDown` library to style the second level drop down list
*
* @returns {undefined}
*/
const styleLevelTwoDropDown = function () {
// Create our dropdown list using `vanillaSelectBox`
new vanillaSelectBox("#drop-down--aggregation-type", {
"disableSelectAll": true,
"maxSelect": 1,
"placeHolder": "--Select--",
"search": false,
});
};
/**
* Use the `vanillaDropDown` library to style the third level drop down list
*
* @returns {undefined}
*/
const styleLevelThreeDropDown = function () {
// Create our dropdown list using `vanillaSelectBox`
new vanillaSelectBox("#drop-down--sampling-rate", {
"disableSelectAll": true,
"maxSelect": 1,
"placeHolder": "--Select--",
"search": false,
});
};
/**
* Use the `vanillaDropDown` library to style the fourth level drop down list
*
* @returns {undefined}
*/
const styleLevelFourDropDown = function () {
// Create our dropdown list using `vanillaSelectBox`
new vanillaSelectBox("#drop-down--chart-type", {
"disableSelectAll": true,
"maxSelect": 1,
"placeHolder": "--Select--",
"search": false,
});
};
/**
* Callback function that wraps the logic of populating the linked drop down lists.
* Will run on `DOMContentLoaded` event
*
* @returns {undefined}
*/
const afterDocumentLoads = function () {
styleLevelOneDropDown();
styleLevelTwoDropDown();
styleLevelThreeDropDown();
styleLevelFourDropDown();
};
/**
* Get the selected option(s) from a dropdown list
*
......@@ -126,7 +22,6 @@ const getSelectedOptionsFromDropDownList = function (selectorStr) {
/**
* Process the selected option(s) from a buildings & data points dropdown list.
* This is currently the first dropdown list in the UI.
*
* @param {Array} selectedOptionsArr An array of string(s) representing the value(s) of the selected `<option>` elements
* @returns {Array} An array of string(s) representing the processed value(s) of the selected buildings & data points option(s)
......@@ -138,10 +33,9 @@ const processSelectionsFromBuildingDataPointOptions = function (
const selectedOptionsBuildingDataPointArr = [];
selectedOptionsArr.forEach((optionStr) => {
// Case 1: <option> element's value CONTAINS a "/" character
// We wish to create a string like this `Bau 101/VL`
if (optionStr.includes("/")) {
// Case 1: <option> element's value CONTAINS a "/" character
// We wish to create a string like this `Bau 101/VL`
// Split the <option> element's value into two substrings
const optionsStrPartOne = optionStr.slice(0, 3);
const optionsStrPartTwo = optionStr.slice(3);
......@@ -153,9 +47,10 @@ const processSelectionsFromBuildingDataPointOptions = function (
const optionsStrNew = optionsStrPartOneNew + optionsStrPartTwo;
selectedOptionsBuildingDataPointArr.push(optionsStrNew);
} else {
// Case 2: <option> element's value DOES NOT CONTAIN a "/" character
// We wish to create a string like this `Other/Außentemp`
}
// Case 2: <option> element's value DOES NOT CONTAIN a "/" character
// We wish to create a string like this `Other/Außentemp`
else {
selectedOptionsBuildingDataPointArr.push(`Other/${optionStr}`);
}
});
......@@ -166,11 +61,23 @@ const processSelectionsFromBuildingDataPointOptions = function (
/**
* Split an option element's value (a string) using a forward slash character ("/") as the delimiter
*
* @param {String} selectedOptionsStr A string representing the value of the selected `<option>` element
* @returns {String} Resulting strings after splitting
*/
const splitOptionsTextDelimitedBySlash = function (selectedOptionsStr) {
return selectedOptionsStr.split("/");
};
/**
* Split an array of option element's values (strings) which have a forward slash character ("/") as the delimiter
*
* @param {Array} selectedOptionsArr An array of string(s) representing the value(s) of the selected `<option>` elements
* @returns {Array} An array made up of resulting strings after splitting
*/
const splitOptionsTextDelimitedBySlash = function (selectedOptionsArr) {
return selectedOptionsArr.map((selectedOption) => selectedOption.split("/"));
const splitMultipleOptionsTextDelimitedBySlash = function (selectedOptionsArr) {
return selectedOptionsArr.map((selectedOption) =>
splitOptionsTextDelimitedBySlash(selectedOption)
);
};
/**
......@@ -185,7 +92,9 @@ const getSelectedOptionsFromAllDropDownLists = function () {
// Separate the building ID from the data point
const selectedBuildingDataPointOptionsSplitArr =
splitOptionsTextDelimitedBySlash(selectedBuildingDataPointOptionsArr);
splitMultipleOptionsTextDelimitedBySlash(
selectedBuildingDataPointOptionsArr
);
const selectedAggregationOptionsArr = getSelectedOptionsFromDropDownList(
"#drop-down--aggregation-type"
......@@ -200,7 +109,6 @@ const getSelectedOptionsFromAllDropDownLists = function () {
);
// Ensure that all the options have at least one selection
if (
selectedBuildingDataPointOptionsSplitArr.length === 0 ||
selectedAggregationOptionsArr.length === 0 ||
......@@ -217,6 +125,177 @@ const getSelectedOptionsFromAllDropDownLists = function () {
];
};
/**
* Check whether the abbreviated buildings + data points + sampling rate strings
* contain the temperature difference [dT] between Vorlauf temperature [VL] and
* Rücklauf temperature [RL] (i.e., dT = VL - RL). Unlike all the other data points,
* this data point is computed in a separate step
*
* @param {Array} buildingDataPointSamplingRateAbbrevArr An array that contains nested array(s) made up of strings representing the abbreviated building + data point + sampling rate values
* @returns {Boolean} true if the selected options contain the string `dT`, false otherwise
*/
const checkIfSelectedOptionsContainTemperatureDifference = function (
buildingDataPointSamplingRateAbbrevArr
) {
// Create a flattened copy of our input array,
// then check if it contains the string `dT`
return buildingDataPointSamplingRateAbbrevArr.flat().includes("dT");
};
/**
* Get the index(es) of the the abbreviated buildings + data points + sampling rate string(s)
* that contains the temperature difference (dT)
*
* @param {Array} buildingDataPointSamplingRateAbbrevArr An array that contains nested array(s) made up of abbreviated building + data point + sampling rate string(s)
* @returns {Array} An array that contains an integer(s) whose value(s) are the index(es) of the abbreviated building + data point + sampling rate string(s) containing the temperature difference (dT)
*/
const getIndexesOfTemperatureDifferenceOptions = function (
buildingDataPointSamplingRateAbbrevArr
) {
// An array to store the final result
const foundIndexesArr = [];
// Use the index, i, provided by `forEach` array method
buildingDataPointSamplingRateAbbrevArr.forEach(
(bldgDataPntSamplingRateAbbrvArr, i) => {
if (bldgDataPntSamplingRateAbbrvArr.includes("dT")) {
foundIndexesArr.push(i);
}
}
);
return foundIndexesArr;
};
/**
* Delete the abbreviated building + data point + sampling rate string(s) that contains the temperature difference (dT)
*
* @param {Array} buildingDataPointSamplingRateAbbrevArr An array that contains nested array(s) made up of abbreviated building + data point + sampling rate string(s)
* @returns {Array} An array that contains nested array(s) made up of abbreviated building + data point + sampling rate string(s)
*/
const deleteTemperatureDifferenceOptions = function (
buildingDataPointSamplingRateAbbrevArr
) {
// Calculate the index(es) that we wish to delete
const foundIndexesArr = getIndexesOfTemperatureDifferenceOptions(
buildingDataPointSamplingRateAbbrevArr
);
// Delete the index(es) of `dT`, modifies the array in place
// Note: The resulting array is sparse
foundIndexesArr.forEach(
(foundIndex) => delete buildingDataPointSamplingRateAbbrevArr[foundIndex]
);
// Array to store our final result
const buildingDataPointFinalArr = [];
// Remove the empty sub array(s) that makes entire array sparse
// Note: `empty` does not mean `undefined` or `null`
buildingDataPointSamplingRateAbbrevArr.forEach(
(bldgDataPntSmplingRateAbbrvArr) => {
if (typeof bldgDataPntSmplingRateAbbrvArr === "object") {
buildingDataPointFinalArr.push(bldgDataPntSmplingRateAbbrvArr);
}
}
);
return buildingDataPointFinalArr;
};
/**
* Extract the abbreviated building + data point + sampling rate string(s) that contains the temperature difference (dT)
*
* @param {Array} buildingDataPointSamplingRateAbbrevArr An array that contains nested array(s) made up of abbreviated building + data point + sampling rate string(s)
* @returns {Array} An array that contains nested array(s) made up of abbreviated building + data point + sampling rate string(s)
*/
const extractTemperatureDifferenceOptions = function (
buildingDataPointSamplingRateAbbrevArr
) {
// Array to store final result
const temperatureDifferenceOptionsAbbrevArr = [];
// Calculate the index(es) that we wish to extract
const foundIndexesArr = getIndexesOfTemperatureDifferenceOptions(
buildingDataPointSamplingRateAbbrevArr
);
foundIndexesArr.forEach((foundIndex) => {
// Extracted array for a single found index
const bldgDataPntSamplingRateAbbrvArr =
buildingDataPointSamplingRateAbbrevArr[foundIndex];
// Extract the building and sampling rate strings
// Note: we have ignored the second element
// const [bldgAbbrv, , samplingRateAbbrv] = bldgDataPntSamplingRateAbbrvArr;
// Create a new array that contains two elements,
// the building and sampling rate abbreviated strings
// const bldgSamplingRateAbbrvArr = [bldgAbbrv, samplingRateAbbrv];
temperatureDifferenceOptionsAbbrevArr.push(bldgDataPntSamplingRateAbbrvArr);
});
return temperatureDifferenceOptionsAbbrevArr;
};
/**
* Extract the abbreviated building + sampling rate string(s) for use in calculating the temperature difference (dT = VL - RL)
*
* @param {Array} buildingDataPointSamplingRateAbbrevArr An array that contains nested array(s) made up of abbreviated building + data point + sampling rate string(s)
* @returns {Array} An array that contains nested array(s) made up of abbreviated building + sampling rate string(s)
*/
const extractBuildingPlusSamplingRate = function (
buildingDataPointSamplingRateAbbrevArr
) {
// Array to store final result
const temperatureDifferenceOptionsAbbrevArr = [];
// Calculate the index(es) that we wish to extract
const foundIndexesArr = getIndexesOfTemperatureDifferenceOptions(
buildingDataPointSamplingRateAbbrevArr
);
foundIndexesArr.forEach((foundIndex) => {
// Extracted array for a single found index
const bldgDataPntSamplingRateAbbrvArr =
buildingDataPointSamplingRateAbbrevArr[foundIndex];
// Extract the building and sampling rate strings
// Note: we have ignored the second element
const [bldgAbbrv, , samplingRateAbbrv] = bldgDataPntSamplingRateAbbrvArr;
// Create a new array that contains two elements,
// the building and sampling rate abbreviated strings
const bldgSamplingRateAbbrvArr = [bldgAbbrv, samplingRateAbbrv];
temperatureDifferenceOptionsAbbrevArr.push(bldgSamplingRateAbbrvArr);
});
return temperatureDifferenceOptionsAbbrevArr;
};
/**
* Determine if a chart requires raw observations instead of aggregated observations
*
* @param {String} selectedAggregationType The selected aggregation type
* @param {String} selectedAggregationDuration The selected aggregation duration
* @returns {Boolean} true if the chart requires raw observations, false if not
*/
const checkIfChartRequiresRawObservations = function (
selectedAggregationType,
selectedAggregationDuration
) {
if (
selectedAggregationType === "None (raw data)" &&
selectedAggregationDuration === undefined
) {
return true;
} else {
return false;
}
};
/**
* Get the abbreviated form of building IDs, phenomenon names and sensor sampling rates
* @param {String} buildingFullForm A string representation of the full form of a building ID
......@@ -239,17 +318,18 @@ const getBuildingSensorSamplingRateAbbreviation = function (
"Bau 225": "225",
"Other": "weather_station_521",
},
phenomenon: {
VL: "vl",
RL: "rl",
dT: "dT",
Durchfluss: "flow",
Leistung: "power",
Energie: "energy",
Energie_VERBR: "energy_verb",
Außentemp: "outside_temp",
},
samplingRate: {
"15 min": "15min",
"60 min": "60min",
......@@ -330,88 +410,13 @@ const getAbbreviationsForSelectedOptionsFromAllDropDownLists = function (
);
};
/**
* Callback function for chart selection using drop down list
* @returns {undefined}
*/
const selectChartTypeFromDropDown = async function () {
try {
const selectedOptions = getSelectedOptionsFromDropDownLists();
if (selectedOptions === undefined) return;
const selectedOptionsAbbreviationsArr =
getBuildingSensorSamplingRateAbbreviation(...selectedOptions);
const selectedChartType = document.querySelector(
"#drop-down--chart-type"
).value;
if (selectedChartType === "--Select--") return;
// Display the loading indicator
showLoadingSpinner();
// The `getMetadataPlusObservationsFromSingleOrMultipleDatastreams` function expects a nested array structure
const abbreviationsNestedArr = [selectedOptionsAbbreviationsArr];
const observationsPlusMetadata =
await getMetadataPlusObservationsFromSingleOrMultipleDatastreams(
BASE_URL,
QUERY_PARAMS_COMBINED,
abbreviationsNestedArr
);
// Extract the combined arrays for observations and metadata
const [observationsNestedArr, metadataNestedArr] = observationsPlusMetadata;
// Create formatted array(s) for observations - line chart
const formattedObsLineChartNestedArr = observationsNestedArr.map(
(observationsArr) =>
formatSensorThingsApiResponseForLineOrColumnChart(observationsArr)
);
// Create formatted array(s) for observations - heatmap
const formattedObsHeatMapNestedArr = observationsNestedArr.map(
(observationsArr) =>
formatSensorThingsApiResponseForHeatMap(observationsArr)
);
// Create formatted array(s) for metadata - same for both chart types
const formattedMetadataArr = metadataNestedArr.map((metadataObj) =>
formatDatastreamMetadataForChart(metadataObj)
);
// Extract the formatted metadata properties
const extractedFormattedDatastreamProperties =
extractPropertiesFromFormattedDatastreamMetadata(
formattedMetadataArr,
false
);
if (selectedChartType === "Line") {
drawLineChartHighcharts(
formattedObsLineChartNestedArr,
extractedFormattedDatastreamProperties
);
} else if (selectedChartType === "Heatmap") {
// First need to extract the formatted observations from the nested array
// Heatmap only needs one set of formatted observation values
drawHeatMapHighcharts(
...formattedObsHeatMapNestedArr,
extractedFormattedDatastreamProperties
);
}
} catch (err) {
console.error(err);
} finally {
// Hide the loading indicator
hideLoadingSpinner();
}
export {
splitMultipleOptionsTextDelimitedBySlash,
getSelectedOptionsFromAllDropDownLists,
checkIfSelectedOptionsContainTemperatureDifference,
deleteTemperatureDifferenceOptions,
extractTemperatureDifferenceOptions,
extractBuildingPlusSamplingRate,
checkIfChartRequiresRawObservations,
getAbbreviationsForSelectedOptionsFromAllDropDownLists,
};
document.addEventListener("DOMContentLoaded", afterDocumentLoads);
document
.querySelector("#drop-down--chart-type")
.addEventListener("change", selectChartTypeFromDropDown);
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment