UNPKG

@iapps/visualization

Version:

90-90-90 HIV Prevention, Engagement and Care Cascade Graph(i.e Treatment target graph to help end the AIDS epidemic)

777 lines (742 loc) 15.5 kB
const _ = require('lodash'); /** * * @param {boolean} useCustomChartTitle * @param {boolean} useCustomXAxisTitle * @param {string} config * @param {string} context * @param {string} ctype * @param {object} chartObject * @param {object} chartExtension * @param {number} initialTarget */ /** * No arguements */ const getLegendConfigurations = () => { return { reversed: true, enabled: false, }; }; /** * * @param {number} pos */ const getColorOptionForTargetedValue = (pos, chartExtension, config) => { if (config === 'global') { if (pos > 0) { return '#ffffff'; } else { return _.has(chartExtension, 'specialChartType') && chartExtension.specialChartType.color !== '' ? chartExtension.specialChartType.color : '#66ccff'; } } else { if (pos >= 1 && pos <= 2) { return '#ffffff'; } else { return _.has(chartExtension, 'specialChartType') && chartExtension.specialChartType.color !== '' ? chartExtension.specialChartType.color : '#66ccff'; } } }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getIndicatorPerformanceDataValues = (initialTarget, chartObject) => { return chartObject && _.has(chartObject, 'series') && initialTarget ? [initialTarget].concat( _.map(chartObject.series, item => parseFloat(item.data[0].y)) ) : []; }; /** * * @param {number} initialTarget * @param {object} chartObject */ const findSummation = (initialTarget, chartObject) => { const indicatorArray = getIndicatorPerformanceDataValues( initialTarget, chartObject ); const indicatorData = [ indicatorArray[indicatorArray.length - 1], indicatorArray[indicatorArray.length - 2], ]; return indicatorData ? indicatorData.reduce((a, b) => a + b, 0) : 0; }; /** * * @param {number} pos * @param {number} initialTarget * @param {array} sanitizedSeriesData */ const getTargetsValueBasedOnPercentages = ( pos, initialTarget, sanitizedSeriesData, config ) => { if (config === 'global') { if (pos === 0) { return initialTarget; } else if (pos === 1) { return parseFloat(calculate90Percent(initialTarget).toFixed(2)); } else if (pos === 2) { return parseFloat( calculate90Percent(calculate90Percent(initialTarget)).toFixed(2) ); } else if (pos === 3) { return parseFloat( calculate90Percent( calculate90Percent(calculate90Percent(initialTarget)) ).toFixed(2) ); } } else { if (pos === 0) { return initialTarget; } else if (pos === 1) { return parseFloat(calculate90Percent(initialTarget).toFixed(2)); } else if (pos === 2) { return parseFloat( calculate90Percent(calculate90Percent(initialTarget)).toFixed(2) ); } else if (pos >= 3 && pos <= 4) { return parseFloat(sanitizedSeriesData[pos].toFixed(2)); } } }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getTotalIndicatorValue = (initialTarget, chartObject) => { return initialTarget && chartObject ? findSummation(initialTarget, chartObject) : 0; }; /** * */ const getTooltipCOnfiguration = () => { return { enabled: true, }; }; /** * * @param {number} pos * @param {number} initialTarget * @param {array} sanitizedSeriesData */ const getAchievedIndicatorsAgainstTargets = ( pos, sanitizedSeriesData, config ) => { if (config === 'global') { if (pos > 0) { return sanitizedSeriesData ? sanitizedSeriesData[pos] : 0; } } else { if (pos >= 1 && pos <= 2) { return sanitizedSeriesData ? sanitizedSeriesData[pos] : 0; } } }; const calculate90Percent = value => { if (value) { return value * (90 / 100); } }; /** * * @param {number} data * @param {number} pos * @param {array} sanitizedSeriesData * @param {number} initialTarget * @param {object} chartObject */ const calculatePercentForArchievedValue = ( pos, sanitizedSeriesData, initialTarget, config ) => { if (config === 'global') { if (pos === 1) { return parseFloat( ( (sanitizedSeriesData[pos] / calculate90Percent(initialTarget)) * 100 ).toFixed(2) ); } else if (pos === 2) { return parseFloat( ( (sanitizedSeriesData[pos] / calculate90Percent(calculate90Percent(initialTarget))) * 100 ).toFixed(2) ); } else if (pos === 3) { return parseFloat( ( (sanitizedSeriesData[pos] / calculate90Percent( calculate90Percent( calculate90Percent(initialTarget) ) )) * 100 ).toFixed(2) ); } } else { if (pos === 1) { return parseFloat( ( (sanitizedSeriesData[pos] / calculate90Percent(initialTarget)) * 100 ).toFixed(2) ); } else if (pos === 2) { return parseFloat( ( (sanitizedSeriesData[pos] / calculate90Percent(calculate90Percent(initialTarget))) * 100 ).toFixed(2) ); } else if (pos === 3) { return 100; } } }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getLastColumnIndicatorPercentage = (initialTarget, chartObject) => { const indicatorArray = getIndicatorPerformanceDataValues( initialTarget, chartObject ); return indicatorArray ? parseFloat( ( (indicatorArray[indicatorArray.length - 1] / indicatorArray[indicatorArray.length - 2]) * 100 ).toFixed(2) ) : 0; }; // // ToDo: START - Deprecated Implementation // /** // * // * @param {number} initialTarget // * @param {object} chartObject // */ // const getLastColumnIndicatorPercentageDeprecated = (initialTarget, chartObject) => { // const indicatorArray = getIndicatorPerformanceDataValues( // initialTarget, // chartObject // ); // const total = getTotalIndicatorValue(initialTarget, chartObject); // return indicatorArray && total // ? parseFloat( // ( // (indicatorArray[indicatorArray.length - 2] / total) * // 100 // ).toFixed(2) // ) // : 0; // }; // // ToDo: END - Deprecated Implementation /** * * @param {number} pos */ const getColorOptionForTargetValues = chartExtension => { return _.has(chartExtension, 'specialChartType') && chartExtension.specialChartType.color !== '' ? chartExtension.specialChartType.color : '#66ccff'; }; /** * * @param {number} data * @param {number} pos * @param {array} sanitizedSeriesData * @param {number} initialTarget * @param {object} chartObject */ const calculatePercentForTargetedValue = ( pos, initialTarget, chartObject, config ) => { if (config === 'global') { if (pos > 0) { return `90%`; } } else { if (pos === 0 && pos === 3) { return ``; } else if (pos >= 1 && pos <= 2) { return `90%`; } else if (pos === 4) { return ( getLastColumnIndicatorPercentage( initialTarget, chartObject ).toFixed(2) + `%` ); } } }; /** * * @param {string} ctype * @param {object} chartObject */ const getChartTypeConfiguration = (ctype, chartObject) => { return ctype !== undefined ? { ...chartObject.chart, type: ctype } : { ...chartObject.chart, type: 'column' }; }; /** * * @param {boolean} useCustomChartTitle * @param {object} chartObject * @param {object} favoriteExtension */ const getChartTitleConfiguration = ( useCustomChartTitle, chartObject, favoriteExtension ) => { return useCustomChartTitle ? { ...chartObject.title, text: favoriteExtension.name } : { ...chartObject.title, text: chartObject.title.text }; }; /** * * @param {Array} axisLabels * @param {Object} chartObject */ const getPeriodAppendedOnChartCategories = (axisLabels, chartObject) => { if (axisLabels) { return _.map(axisLabels, (axisLabel, index) => { return index === 3 || index === 4 ? axisLabel + ' <b>(' + chartObject.xAxis.categories[0].name + ')</b>' : axisLabel; }); } }; // START: Modified Cascade Series /** * * @param {*} chartObject * @param {*} favoriteExtensions */ const getXAxisCustomCategories = (chartObject, favoriteExtensions, config) => { if (chartObject) { if (_.has(chartObject, 'series')) { const sanitizedCategories = getCascadeCategories( getUniqueCategories( _.uniq( _.map(chartObject.series, series => { return _.has(favoriteExtensions, 'extensions') ? _.map( favoriteExtensions.extensions, extension => { return series.id === extension.id ? { name: extension.name, position: extension.position, } : { name: extension.name, position: extension.position, }; } ) : []; }) ), 'name' ) ); return config !== 'global' ? getPeriodAppendedOnChartCategories( sanitizedCategories, chartObject ) : sanitizedCategories; } else { console.log('Chart has no series'); } } else { console.log('No Chart Object found'); } }; /** * * @param {*} uniqueCategories */ const getCascadeCategories = uniqueCategories => { return _.map(uniqueCategories, category => { return category.name; }); }; /** * * @param {*} categories * @param {*} criteria */ const getUniqueCategories = (categories, criteria) => { const uniqueCategories = _.uniqBy(_.flattenDeep(categories), criteria); return getSortedCategoriesBasedOnFavoriteExtensionPosition( uniqueCategories, 'position' ); }; /** * * @param {*} uniqueCategories * @param {*} criteria */ const getSortedCategoriesBasedOnFavoriteExtensionPosition = ( uniqueCategories, criteria ) => { return _.sortBy(uniqueCategories, criteria); }; // END: Modified Cascade Series /** * * @param {*} chartObject */ const getFavoritteXAxisLabels = chartObject => { return chartObject && _.has(chartObject, 'series') ? _.map(chartObject.series, series => series.name) : []; }; /** * * @param {boolean} useCustomXAxisTitle * @param {object} chartObject * @param {object} favoriteExtensions */ const getXAxisChartConfigurations = ( useCustomXAxisTitle, chartObject, favoriteExtensions, config ) => { return useCustomXAxisTitle ? getXAxisCustomCategories(chartObject, favoriteExtensions, config) : getFavoritteXAxisLabels(chartObject); }; const getYAxisChartConfigurations = chartExtension => { return { title: { text: '', }, stackLabels: { style: { color: 'black', }, enabled: true, verticalAlign: 'top', }, max: _.has(chartExtension, 'multiAxisLabels') ? chartExtension.multiAxisLabels[0].yAxis.max : '', min: _.has(chartExtension, 'multiAxisLabels') ? chartExtension.multiAxisLabels[0].yAxis.min : '', }; }; const getPlotOptionsConfigurations = () => { return { series: { dataLabels: { enabled: true, inside: true, }, stacking: 'normal', grouping: false, shadow: false, borderWidth: 0, enableMouseTracking: false, allowPointSelect: true, verticalAlign: 'top', align: 'center', }, }; }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getSanitizedSeriesTargetValue = (initialTarget, chartObject) => { return getIndicatorPerformanceDataValues(initialTarget, chartObject); }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getArchievedSeriesData = ( initialTarget, chartObject, chartExtension, config ) => { const sanitizedSeriesData = getSanitizedSeriesTargetValue( initialTarget, chartObject ); return _.map(sanitizedSeriesData, (data, pos) => { if (config === 'global') { return { y: getAchievedIndicatorsAgainstTargets( pos, sanitizedSeriesData, config ), percent: calculatePercentForArchievedValue( pos, sanitizedSeriesData, initialTarget, config ), color: getColorOptionForTargetValues(chartExtension), }; } else { if (pos >= 1 && pos <= 2) { return { y: getAchievedIndicatorsAgainstTargets( pos, sanitizedSeriesData ), percent: calculatePercentForArchievedValue( pos, sanitizedSeriesData, initialTarget, config ), color: getColorOptionForTargetValues(chartExtension), }; } else { return { percent: calculatePercentForArchievedValue( pos, sanitizedSeriesData, initialTarget ), color: getColorOptionForTargetValues(chartExtension), }; } } }); }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getArchievedSeriesValue = ( initialTarget, chartObject, chartExtension, config ) => { return { name: 'Achieved', stack: 2, zIndex: 2, pointPadding: 0, dataLabels: [ { align: 'center', format: '{point.percent}%', verticalAlign: 'top', style: { color: 'black', }, }, ], data: getArchievedSeriesData( initialTarget, chartObject, chartExtension, config ), }; }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getInitializedSeriesData = ( initialTarget, chartObject, chartExtension, config ) => { const sanitizedSeriesData = getSanitizedSeriesTargetValue( initialTarget, chartObject ); return _.map(sanitizedSeriesData, (data, pos) => { return { y: Math.floor( getTargetsValueBasedOnPercentages( pos, initialTarget, sanitizedSeriesData, config ) ), percent: calculatePercentForTargetedValue( pos, initialTarget, chartObject, config ), color: getColorOptionForTargetedValue(pos, chartExtension, config), }; }); }; /** * * @param {number} initialTarget * @param {object} chartObject */ const getTargetedSeriedValue = ( initialTarget, chartObject, chartExtension, config ) => { return { name: 'Targets', stack: 1, zIndex: 1, pointPadding: 0, dashStyle: 'dash', borderColor: _.has(chartExtension, 'specialChartType') && chartExtension.specialChartType.color !== '' ? chartExtension.specialChartType.color : '#66ccff', borderWidth: 2, dataLabels: [ { align: 'center', format: '{point.percent}', verticalAlign: 'top', style: { color: 'black', }, }, ], data: getInitializedSeriesData( initialTarget, chartObject, chartExtension, config ), }; }; /** * * @param {boolean} initialTarget * @param {*} chartObject */ const getSeriesConfigurations = ( initialTarget, chartObject, chartExtension, config ) => { return [ getTargetedSeriedValue( initialTarget, chartObject, chartExtension, config ), getArchievedSeriesValue( initialTarget, chartObject, chartExtension, config ), ]; }; exports.GenerateCascadeGraph = ( useCustomChartTitle, useCustomXAxisTitle, config, context, ctype, chartObject, chartExtension, initialTarget ) => { return { chart: getChartTypeConfiguration(ctype, chartObject), title: getChartTitleConfiguration( useCustomChartTitle, chartObject, chartExtension ), subtitle: chartObject.subtitle, credits: chartObject.credits, colors: chartObject.colors, xAxis: { categories: getXAxisChartConfigurations( useCustomXAxisTitle, chartObject, chartExtension, config ), }, yAxis: getYAxisChartConfigurations(chartExtension), legend: getLegendConfigurations(), plotOptions: getPlotOptionsConfigurations(), tooltip: chartObject.exporting, exporting: chartObject.exporting, series: getSeriesConfigurations( initialTarget, chartObject, chartExtension, config ), }; };