Commit dcee9d35 authored by Pithon Kabiro's avatar Pithon Kabiro
Browse files

Edit function: callback function that draws chart

Check the structure of the arrays of observations + metadata. Throw
errors if there is a problem fetching metadata and observations
parent bee78fb8
...@@ -228,18 +228,35 @@ const drawChartUsingSelectedOptions = async function () { ...@@ -228,18 +228,35 @@ const drawChartUsingSelectedOptions = async function () {
) )
); );
// If there is an error in fetching metadata + observations (Case 1: raw observations)
// the returned array will have this structure: [[undefined, undefined], undefined]
// Note that the second element is not an array as we would expect but is a
// a single `undefined` value
if (typeof observationsRawPlusMetadataArr[0][0] === "undefined") {
throw new Error(
`There was a problem in fetching metadata and observations`
);
}
// If there is an error in fetching metadata + observations (Case 2: temperature difference, dT)
// a single `undefined` value instead of an array (as we would expect) will be returned
if (typeof observationsTempDiffPlusMetadataArr === "undefined")
throw new Error(
`There was a problem in calculating the temperature difference (dT).\nThis is most likely due to a problem in fetching metadata and observations`
);
// Extract the combined arrays for observations and metadata / raw observations // Extract the combined arrays for observations and metadata / raw observations
const [observationsRawNestedArr, metadataTempDiffNestedArr] = const [observationsRawNestedArr, metadataRawNestedArr] =
observationsRawPlusMetadataArr; observationsRawPlusMetadataArr;
// Extract the combined arrays for observations and metadata / temperature difference (dT) // Extract the combined arrays for observations and metadata / temperature difference (dT)
const [observationsNestedComputedArr, metadataNestedComputedArr] = const [observationsTempDiffNestedArr, metadataTempDiffNestedArr] =
observationsTempDiffPlusMetadataArr; observationsTempDiffPlusMetadataArr;
// Create a combined array of observations and metadata // Create a combined array of observations and metadata
const observationsPlusMetadataCombined = [ const observationsPlusMetadataCombined = [
[...observationsRawNestedArr, ...observationsNestedComputedArr], [...observationsRawNestedArr, ...observationsTempDiffNestedArr],
[...metadataTempDiffNestedArr, ...metadataNestedComputedArr], [...metadataRawNestedArr, ...metadataTempDiffNestedArr],
]; ];
const [observationsComboNestedArr, metadataComboNestedArr] = const [observationsComboNestedArr, metadataComboNestedArr] =
...@@ -384,6 +401,9 @@ const drawChartUsingSelectedOptions = async function () { ...@@ -384,6 +401,9 @@ const drawChartUsingSelectedOptions = async function () {
} }
} catch (err) { } catch (err) {
console.error(err); console.error(err);
// Display a dialog window with the error message
alert(err);
} finally { } finally {
// Enable the 'draw chart' button // Enable the 'draw chart' button
enableDrawChartButton(); enableDrawChartButton();
......
...@@ -252,58 +252,67 @@ const extractObservationValuesWithinMonthInterval = function ( ...@@ -252,58 +252,67 @@ const extractObservationValuesWithinMonthInterval = function (
samplingRate, samplingRate,
calendarMonthStr calendarMonthStr
) { ) {
// Extract the year and month digits from the calendar month string try {
const [yearNum, monthNum] = // Extract the year and month digits from the calendar month string
extractMonthYearDigitsFromCalendarMonthString(calendarMonthStr); const [yearNum, monthNum] =
extractMonthYearDigitsFromCalendarMonthString(calendarMonthStr);
// All the months start on the first // All the months start on the first
const startDateStr = `${calendarMonthStr}-01`; const startDateStr = `${calendarMonthStr}-01`;
if (monthNum < 1 || monthNum > 12) { if (monthNum < 1 || monthNum > 12) {
throw new Error("The specified digit for the month of the year is invalid"); throw new Error(
} "The specified digit for the month of the year is invalid"
// February );
else if (monthNum === 2) { }
// Leap year // February
if (checkIfLeapYear(yearNum)) { else if (monthNum === 2) {
// Leap year
if (checkIfLeapYear(yearNum)) {
return extractObservationValuesWithinDatesInterval(
obsArray,
samplingRate,
startDateStr,
`${calendarMonthStr}-29`
);
}
// Non-leap year
else {
return extractObservationValuesWithinDatesInterval(
obsArray,
samplingRate,
startDateStr,
`${calendarMonthStr}-28`
);
}
}
// Months with 30 days
else if (
monthNum === 4 ||
monthNum === 6 ||
monthNum === 9 ||
monthNum === 11
) {
return extractObservationValuesWithinDatesInterval( return extractObservationValuesWithinDatesInterval(
obsArray, obsArray,
samplingRate, samplingRate,
startDateStr, startDateStr,
`${calendarMonthStr}-29` `${calendarMonthStr}-30`
); );
} }
// Non-leap year // Months with 31 days
else { else {
return extractObservationValuesWithinDatesInterval( return extractObservationValuesWithinDatesInterval(
obsArray, obsArray,
samplingRate, samplingRate,
startDateStr, startDateStr,
`${calendarMonthStr}-28` `${calendarMonthStr}-31`
); );
} }
} } catch (err) {
// Months with 30 days // Rethrow errors from `getIndexOfStartTimestamp` or `getIndexOfEndTimestamp` functions
else if ( throw new Error(
monthNum === 4 || `${err.message} \nCurrently, the monthly aggregation does not support partial calendar months`
monthNum === 6 ||
monthNum === 9 ||
monthNum === 11
) {
return extractObservationValuesWithinDatesInterval(
obsArray,
samplingRate,
startDateStr,
`${calendarMonthStr}-30`
);
}
// Months with 31 days
else {
return extractObservationValuesWithinDatesInterval(
obsArray,
samplingRate,
startDateStr,
`${calendarMonthStr}-31`
); );
} }
}; };
......
...@@ -175,6 +175,16 @@ export const calculateVorlaufMinusRuecklaufTemperature = async function ( ...@@ -175,6 +175,16 @@ export const calculateVorlaufMinusRuecklaufTemperature = async function (
bldgDataPtSamplingRateNestedArr bldgDataPtSamplingRateNestedArr
); );
// If there is an error in fetching metadata + observations,
// the returned array will have this structure: [[undefined, undefined], undefined]
// Note that the second element is not an array as we would expect but is a
// a single `undefined` value
if (typeof observationsPlusMetadata[0][0] === "undefined") {
throw new Error(
`There was a problem in calculating the temperature difference (dT).\nThis is most likely due to a problem in fetching metadata and observations`
);
}
// dT observations (timestamp + value) // dT observations (timestamp + value)
const vorlaufMinusRuecklaufTemperatureObs = const vorlaufMinusRuecklaufTemperatureObs =
calculateVorlaufMinusRuecklaufTemperatureObservations( calculateVorlaufMinusRuecklaufTemperatureObservations(
......
...@@ -24,44 +24,73 @@ const createObservationsUrl = function (baseUrl, datastreamID) { ...@@ -24,44 +24,73 @@ const createObservationsUrl = function (baseUrl, datastreamID) {
return `${baseUrl}/Datastreams(${datastreamID})/Observations`; return `${baseUrl}/Datastreams(${datastreamID})/Observations`;
}; };
/**
* Perform a GET request to fetch a single Datastream using the Axios library
*
* @param {String} urlDatastream A URL that fetches a single Datastream from an STA instance
* @returns {Promise} A promise that contains the Datastream metadata when fulfilled
*/
const getDatastream = function (urlDatastream) {
return axios.get(urlDatastream);
};
/** /**
* Perform a GET request using the Axios library * Perform a GET request using the Axios library
* @param {String} urlObservations A URL that fetches Observations from an STA instance * @param {String} urlObservations A URL that fetches Observations from an STA instance
* @param {Object} urlParamObj The URL parameters to be sent together with the GET request * @param {Object} urlParamObj The URL parameters to be sent together with the GET request
* @returns {Promise} A promise that contains the first page of results when fulfilled * @returns {Promise} A promise that contains the first page of results when fulfilled
*/ */
const performGetRequestUsingAxios = function (urlObservations, urlParamObj) { const getObservations = function (urlObservations, urlParamObj) {
return axios.get(urlObservations, { return axios.get(urlObservations, {
params: urlParamObj, params: urlParamObj,
}); });
}; };
/** /**
* Retrieve the metadata for a single datastream * Extract the metadata from a single datastream
* @async * @async
* @param {String} urlDatastream A URL that fetches a Datastream from an STA instance * @param {String} urlDatastream A URL that fetches a Datastream from an STA instance
* @returns {Promise} A promise that contains a metadata object for a Datastream when fulfilled * @returns {Promise} A promise that contains a metadata object for a Datastream when fulfilled
*/ */
const getMetadataFromSingleDatastream = async function (urlDatastream) { const extractMetadataFromSingleDatastream = async function (urlDatastream) {
try { try {
// Extract properties of interest // Extract properties of interest
const { const {
data: { description, name, unitOfMeasurement }, data: { description, name, unitOfMeasurement },
} = await performGetRequestUsingAxios(urlDatastream); } = await getDatastream(urlDatastream);
return { description, name, unitOfMeasurement }; return { description, name, unitOfMeasurement };
} catch (err) { } catch (err) {
console.error(err); // Server responded with status code outside of 2xx range
if (err.response) {
throw new Error(
`The request to fetch Datastream metadata was made but the server responded with: \n${err.message}`
);
}
// Request was made but no response was received
else if (err.request) {
throw new Error(
`The request to fetch Datastream metadata was made but no response was received: \n${err.message}`
);
}
// Problem with setting up the request
else {
throw new Error(
`There was a problem setting up the request to fetch Datastream metadata: \n${err.message}`
);
}
} }
}; };
/** /**
* Retrieve metadata from multiple datastreams * Extract the metadata from multiple datastreams
* @async * @async
* @param {Array} datastreamsUrlArr An array that contains N Datastream URL strings * @param {Array} datastreamsUrlArr An array that contains N Datastream URL strings
* @returns {Promise} A promise that contains an array of N Datastream metadata objects when fulfilled * @returns {Promise} A promise that contains an array of N Datastream metadata objects when fulfilled
*/ */
const getMetadataFromMultipleDatastreams = async function (datastreamsUrlArr) { const extractMetadataFromMultipleDatastreams = async function (
datastreamsUrlArr
) {
try { try {
// Array to store our final result // Array to store our final result
const datastreamMetadataArr = []; const datastreamMetadataArr = [];
...@@ -69,7 +98,7 @@ const getMetadataFromMultipleDatastreams = async function (datastreamsUrlArr) { ...@@ -69,7 +98,7 @@ const getMetadataFromMultipleDatastreams = async function (datastreamsUrlArr) {
// Use for/of loop - we need to maintain the order of execution of the async operations // Use for/of loop - we need to maintain the order of execution of the async operations
for (const datastreamUrl of datastreamsUrlArr) { for (const datastreamUrl of datastreamsUrlArr) {
// Metadata from a single Datastream // Metadata from a single Datastream
const datastreamMetadata = await getMetadataFromSingleDatastream( const datastreamMetadata = await extractMetadataFromSingleDatastream(
datastreamUrl datastreamUrl
); );
datastreamMetadataArr.push(datastreamMetadata); datastreamMetadataArr.push(datastreamMetadata);
...@@ -109,7 +138,24 @@ const combineResultsFromAllPages = async function (httpGetRequestPromise) { ...@@ -109,7 +138,24 @@ const combineResultsFromAllPages = async function (httpGetRequestPromise) {
return lastSuccess; return lastSuccess;
} }
} catch (err) { } catch (err) {
console.error(err); // Server responded with status code outside of 2xx range
if (err.response) {
throw new Error(
`The request to fetch Observations was made but the server responded with: \n${err.message}`
);
}
// Request was made but no response was received
else if (err.request) {
throw new Error(
`The request to fetch Observations was made but no response was received: \n${err.message}`
);
}
// Problem with setting up the request
else {
throw new Error(
`There was a problem setting up the request to fetch Observations: \n${err.message}`
);
}
} }
}; };
...@@ -208,7 +254,7 @@ const getMetadataPlusObservationsFromSingleOrMultipleDatastreams = ...@@ -208,7 +254,7 @@ const getMetadataPlusObservationsFromSingleOrMultipleDatastreams =
// Promise objects - Observations // Promise objects - Observations
const observationsPromisesArr = observationsUrlArr.map((obsUrl) => const observationsPromisesArr = observationsUrlArr.map((obsUrl) =>
extractCombinedObservationsFromAllPages( extractCombinedObservationsFromAllPages(
performGetRequestUsingAxios(obsUrl, urlParamObj) getObservations(obsUrl, urlParamObj)
) )
); );
...@@ -218,7 +264,7 @@ const getMetadataPlusObservationsFromSingleOrMultipleDatastreams = ...@@ -218,7 +264,7 @@ const getMetadataPlusObservationsFromSingleOrMultipleDatastreams =
); );
// Metadata array // Metadata array
const metadataArr = await getMetadataFromMultipleDatastreams( const metadataArr = await extractMetadataFromMultipleDatastreams(
datastreamsUrlArr datastreamsUrlArr
); );
......
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