diff --git a/components/widgets/fires/fires-alerts-cumulative/selectors.js b/components/widgets/fires/fires-alerts-cumulative/selectors.js index a589cc86d0..3a9707015a 100644 --- a/components/widgets/fires/fires-alerts-cumulative/selectors.js +++ b/components/widgets/fires/fires-alerts-cumulative/selectors.js @@ -32,6 +32,7 @@ const getSentences = (state) => state.sentences || null; const getLocationName = (state) => state.locationLabel; const getOptionsSelected = (state) => state.optionsSelected; const getIndicator = (state) => state.indicator; +const getSettings = (state) => state.settings; export const getCompareYears = createSelector( [getCompareYear, getAllYears], @@ -401,9 +402,9 @@ export const parseSentence = createSelector( getDataset, getLocationName, getStartIndex, - // getEndIndex, getOptionsSelected, getIndicator, + getSettings, ], ( raw_data, @@ -413,18 +414,29 @@ export const parseSentence = createSelector( dataset, location, startIndex, - // endIndex //broken? options, - indicator + indicator, + settings ) => { if (!data || isEmpty(data)) return null; + const { highConfidence, allAlerts, highConfidenceWithInd, allAlertsWithInd, } = sentences; - const { confidence } = options; + const { confidenceToggle } = settings; + let { confidence } = options; + + /* + Validation for the Analysis + */ + if (confidenceToggle) { + confidence = + confidenceToggle === 'true' ? { value: 'h' } : { value: 'all' }; + } + const indicatorLabel = indicator && indicator.label ? indicator.label : null; const start = startIndex; diff --git a/components/widgets/fires/fires-alerts-historical-daily/selectors.js b/components/widgets/fires/fires-alerts-historical-daily/selectors.js index 513777ce8b..97b82dd117 100644 --- a/components/widgets/fires/fires-alerts-historical-daily/selectors.js +++ b/components/widgets/fires/fires-alerts-historical-daily/selectors.js @@ -11,6 +11,7 @@ const getAlerts = (state) => state.data; const getColors = (state) => state.colors || null; const getStartDate = (state) => state.settings.startDate; const getEndDate = (state) => state.settings.endDate; +const getSettings = (state) => state.settings; const getSentences = (state) => state.sentences || null; const getLocationObject = (state) => state.location; const getOptionsSelected = (state) => state.optionsSelected; @@ -87,6 +88,7 @@ export const parseSentence = createSelector( getEndDate, getOptionsSelected, getIndicator, + getSettings, ], ( data, @@ -96,11 +98,24 @@ export const parseSentence = createSelector( startDate, endDate, options, - indicator + indicator, + settings ) => { if (!data) return null; const { initial, withInd, highConfidence } = sentences; - const { confidence, dataset } = options; + const { confidenceToggle } = settings; + const { dataset } = options; + + let { confidence } = options; + + /* + Validation for the Analysis + */ + if (confidenceToggle) { + confidence = + confidenceToggle === 'true' ? { value: 'h' } : { value: 'all' }; + } + const indicatorLabel = indicator && indicator.label ? indicator.label : null; const total = sumBy(data, 'alert__count'); diff --git a/components/widgets/fires/fires-alerts-historical-old/index.js b/components/widgets/fires/fires-alerts-historical-old/index.js deleted file mode 100644 index bcf93b7b03..0000000000 --- a/components/widgets/fires/fires-alerts-historical-old/index.js +++ /dev/null @@ -1,288 +0,0 @@ -import { fetchHistoricalAlerts } from 'services/analysis-cached'; - -import getWidgetProps from './selectors'; - -export default { - widget: 'firesAlertsHistoricalOld', - title: 'Fire Alerts Count in {location}', - large: true, - categories: ['summary', 'fires'], - settingsConfig: [ - { - key: 'forestType', - label: 'Forest Type', - type: 'select', - placeholder: 'All land cover', - clearable: true, - }, - { - key: 'landCategory', - label: 'Land Category', - type: 'select', - placeholder: 'All categories', - clearable: true, - border: true, - }, - { - key: 'dataset', - label: 'fires dataset', - type: 'select', - }, - { - key: 'confidence', - label: 'Confidence level', - type: 'select', - clearable: false, - border: true, - }, - ], - refetchKeys: [ - 'forestType', - 'landCategory', - 'dataset', - 'endYear', - 'startYear', - 'confidence', - ], - visible: ['dashboard'], - types: ['country'], - admins: ['adm0', 'adm1', 'adm2'], - chartType: 'composedChart', - hideLayers: true, - dataType: 'fires', - colors: 'fires', - metaKey: 'widget_fire_alert_location', - sortOrder: { - fires: 5, - }, - settings: { - startDate: '2020-01-01', - endDate: '2020-04-01', - dataset: 'viirs', - }, - sentences: { - initial: - 'Between {start_year} and {end_year}, {location} experienced a total of {total_alerts} {dataset} fire alerts', - withInd: - 'Between {start_year} and {end_year}, {location} experienced a total of {total_alerts} {dataset} fire alerts within {indicator}', - conf: ', considering {confidence} alerts only.', - }, - whitelists: { - adm0: [ - 'AFG', - 'AGO', - 'ALB', - 'AND', - 'ANT', - 'ARE', - 'ARG', - 'ARM', - 'AUS', - 'AUT', - 'AZE', - 'BDI', - 'BEL', - 'BEN', - 'BFA', - 'BGD', - 'BGR', - 'BHR', - 'BHS', - 'BIH', - 'BLM', - 'BLR', - 'BLZ', - 'BOL', - 'BRA', - 'BRB', - 'BRN', - 'BTN', - 'BWA', - 'CAF', - 'CAN', - 'CHE', - 'CHL', - 'CHN', - 'CIV', - 'CMR', - 'COD', - 'COG', - 'COL', - 'COM', - 'CPV', - 'CRI', - 'CUB', - 'CYP', - 'CZE', - 'DEU', - 'DJI', - 'DMA', - 'DNK', - 'DOM', - 'DZA', - 'ECU', - 'EGY', - 'ERI', - 'ESP', - 'EST', - 'ETH', - 'FIN', - 'FJI', - 'FLK', - 'FRA', - 'FSM', - 'GAB', - 'GBR', - 'GEO', - 'GHA', - 'GIB', - 'GIN', - 'GLP', - 'GMB', - 'GNB', - 'GNQ', - 'GRC', - 'GRL', - 'GTM', - 'GUF', - 'GUM', - 'GUY', - 'HND', - 'HRV', - 'HTI', - 'HUN', - 'IDN', - 'IND', - 'IRL', - 'IRN', - 'IRQ', - 'ISR', - 'ITA', - 'JAM', - 'JOR', - 'JPN', - 'KAZ', - 'KEN', - 'KGZ', - 'KHM', - 'KIR', - 'KNA', - 'KOR', - 'KWT', - 'LAO', - 'LBN', - 'LBR', - 'LBY', - 'LCA', - 'LIE', - 'LKA', - 'LSO', - 'LTU', - 'LUX', - 'LVA', - 'MAR', - 'MCO', - 'MDA', - 'MDG', - 'MDV', - 'MEX', - 'MHL', - 'MKD', - 'MLI', - 'MLT', - 'MMR', - 'MNE', - 'MNG', - 'MNP', - 'MOZ', - 'MRT', - 'MSR', - 'MTQ', - 'MUS', - 'MWI', - 'MYS', - 'NAM', - 'NCL', - 'NER', - 'NGA', - 'NIC', - 'NLD', - 'NOR', - 'NPL', - 'NZL', - 'OMN', - 'PAK', - 'PAN', - 'PCN', - 'PER', - 'PHL', - 'PNG', - 'POL', - 'PRI', - 'PRK', - 'PRT', - 'PRY', - 'PSE', - 'PYF', - 'QAT', - 'REU', - 'ROU', - 'RUS', - 'RWA', - 'SAU', - 'SDN', - 'SEN', - 'SGP', - 'SLB', - 'SLE', - 'SLV', - 'SOM', - 'SRB', - 'SSD', - 'STP', - 'SUR', - 'SVK', - 'SVN', - 'SWE', - 'SWZ', - 'SYR', - 'TCD', - 'TGO', - 'THA', - 'TJK', - 'TKL', - 'TKM', - 'TLS', - 'TON', - 'TTO', - 'TUN', - 'TUR', - 'TUV', - 'TZA', - 'UGA', - 'UKR', - 'URY', - 'USA', - 'UZB', - 'VAT', - 'VEN', - 'VIR', - 'VNM', - 'VUT', - 'WSM', - 'YEM', - 'ZAF', - 'ZMB', - 'ZWE', - ], - }, - getData: (params) => - fetchHistoricalAlerts(params).then((alerts) => { - const { data } = alerts.data; - return data; - }), - getDataURL: (params) => [ - fetchHistoricalAlerts({ ...params, download: true }), - ], - getWidgetProps, -}; diff --git a/components/widgets/fires/fires-alerts-historical-old/selectors.js b/components/widgets/fires/fires-alerts-historical-old/selectors.js deleted file mode 100644 index 07d9860942..0000000000 --- a/components/widgets/fires/fires-alerts-historical-old/selectors.js +++ /dev/null @@ -1,217 +0,0 @@ -import { createSelector, createStructuredSelector } from 'reselect'; -import moment from 'moment'; -import { format } from 'd3-format'; -import isEmpty from 'lodash/isEmpty'; -import sortBy from 'lodash/sortBy'; -import sumBy from 'lodash/sumBy'; -import groupBy from 'lodash/groupBy'; - -import { getDatesData, getChartConfig } from 'components/widgets/utils/data'; - -const getAlerts = state => state.data && state.data.alerts; -const getFrequency = state => state.data && state.data.frequency; -const getColors = state => state.colors || null; -const getStartDate = state => state.settings.startDate; -const getEndDate = state => state.settings.endDate; -const getSentences = state => state.sentences || null; -const getDataset = state => state.settings.dataset || null; -const getLocationObject = state => state.location; -const getOptionsSelected = state => state.optionsSelected; -const getIndicator = state => state.indicator; - -const getDaysArray = (startDate, stopDate) => { - const dateArray = []; - let currentDate = moment(startDate); - const endDate = moment(stopDate); - while (currentDate <= endDate) { - dateArray.push(moment(currentDate).format('YYYY-MM-DD')); - currentDate = moment(currentDate).add(1, 'days'); - } - return dateArray; -}; - -export const getData = createSelector( - [getAlerts, getFrequency, getStartDate, getEndDate], - (data, frequency, startDate, endDate) => { - if (!data || isEmpty(data) || !frequency || !startDate || !endDate) { return null; } - - const startYear = moment(startDate).year(); - const endYear = moment(endDate).year(); - const years = []; - for (let i = startYear; i <= endYear; i += 1) { - years.push(i); - } - - const yearLengths = {}; - years.forEach(y => { - if (moment(`${y}-12-31`).isoWeek() === 1) { - yearLengths[y] = moment(`${y}-12-31`) - .subtract(1, 'week') - .isoWeek(); - } else { - yearLengths[y] = moment(`${y}-12-31`).isoWeek(); - } - }); - - const zeroFilledData = []; - if (frequency === 'daily') { - // why check `alert__date`? Sometimes settings change before refetching, - // and `data` is still the weekly data - - // If we are looking at daily resolution, add week and year and zero-fill - const datesArray = getDaysArray(startDate, endDate); - const dataWithYears = datesArray.map(d => { - const filteredDate = data.find(el => el.alert__date === d); - return { - date: d, - count: - filteredDate && filteredDate.alert__count > 0 - ? filteredDate.alert__count - : 0, - year: moment(d).year(), - week: moment(d).isoWeek(), - dayOfYear: moment(d).dayOfYear() // zero-filling - }; - }); - - const groupedByYear = groupBy( - sortBy(dataWithYears, ['year', 'dayOfYear']), - 'year' - ); - - years.filter(year => year === startYear).forEach(year => { - const yearDataByDay = groupBy(groupedByYear[year], 'dayOfYear'); - const maxDay = - year === moment().year() - ? Object.keys(yearDataByDay).pop() - : moment(`${year}-12-31`).dayOfYear(); - for (let i = 1; i <= maxDay; i += 1) { - zeroFilledData.push( - yearDataByDay[i] - ? yearDataByDay[i][0] - : { - alerts: 0, - count: 0, - week: moment() - .dayOfYear(i) - .isoWeek(), - year: parseInt(year, 10) - } - ); - } - }); - } else { - const groupedByYear = groupBy(sortBy(data, ['year', 'week']), 'year'); - - years.forEach(year => { - const yearDataByWeek = groupBy(groupedByYear[year], 'week'); - const maxWeek = - year === moment().year() - ? Object.keys(yearDataByWeek).pop() - : yearLengths[year]; - for (let i = 1; i <= maxWeek; i += 1) { - zeroFilledData.push( - yearDataByWeek[i] - ? yearDataByWeek[i][0] - : { alerts: 0, count: 0, week: i, year: parseInt(year, 10) } - ); - } - }); - } - return zeroFilledData; - } -); - -export const parseData = createSelector([getData], data => { - if (!data) return null; - // getDatesData: adds date and month info to data array - return getDatesData(data); -}); - -export const parseConfig = createSelector( - [getColors, getFrequency, getDataset], - (colors, frequency, dataset) => { - const tooltip = [ - { - label: 'Fire alerts' - }, - { - key: 'count', - labelKey: 'date', - labelFormat: value => moment(value).format('MMM DD YYYY'), - unit: ` ${dataset.toUpperCase()} alerts`, - color: colors.main, - unitFormat: value => - (Number.isInteger(value) ? format(',')(value) : value) - } - ]; - - return { - ...getChartConfig(colors), - tooltip, - xAxis: { - scale: 'point', - tickCount: 12, - interval: frequency === 'daily' ? 31 : undefined, - tickFormatter: t => moment(t).format('MMM-YY') - } - }; - } -); - -export const parseSentence = createSelector( - [ - parseData, - getColors, - getSentences, - getLocationObject, - getStartDate, - getEndDate, - getOptionsSelected, - getIndicator - ], - ( - data, - colors, - sentences, - location, - startDate, - endDate, - options, - indicator - ) => { - if (!data) return null; - const { dataset, confidence } = options; - const { initial, withInd, conf } = sentences; - const lastDate = data[data.length - 1] || {}; - const firstDate = data[0] || {}; - const total = sumBy( - data.filter(el => el.date >= firstDate.date && el.date <= lastDate.date), - 'count' - ); - const indicatorLabel = - indicator && indicator.label ? indicator.label : null; - const initialSentence = indicator ? withInd : initial; - const sentence = - confidence.value === 'h' ? initialSentence + conf : `${initialSentence}.`; - const params = { - confidence: confidence.value === 'h' ? 'high confidence' : '', - location: location.label || '', - indicator: indicatorLabel, - start_year: moment(startDate).format('Do of MMMM YYYY'), - end_year: moment(endDate).format('Do of MMMM YYYY'), - dataset: dataset && dataset.label, - total_alerts: { - value: total ? format(',')(total) : 0, - color: colors.main - } - }; - return { sentence, params }; - } -); - -export default createStructuredSelector({ - data: parseData, - config: parseConfig, - sentence: parseSentence -}); diff --git a/services/analysis-cached.js b/services/analysis-cached.js index 0eafe2f79d..cadfcb7e27 100644 --- a/services/analysis-cached.js +++ b/services/analysis-cached.js @@ -2288,20 +2288,37 @@ export const fetchVIIRSAlertsSumOTF = (params) => { export const fetchVIIRSAlertsSum = (params) => { const { startDate, endDate, dataset } = params || {}; + /* + * Removing confidence parameter from VIIRS layer options + * for Fire Alerts widget, we always fetch all alerts + * and calculate the values directly on the selector.js + */ + const paramKeys = Object.keys(params).filter( + (param) => param !== 'confidence' + ); + const paramsWithoutConfidenceAlert = {}; + + paramKeys.forEach((parameter) => { + paramsWithoutConfidenceAlert[parameter] = params[parameter]; + }); + const url = encodeURI( `${getRequestUrl({ - ...params, + ...paramsWithoutConfidenceAlert, dataset, datasetType: 'daily', })}${SQL_QUERIES.firesDailySum}` .replace( /{select_location}/g, - getLocationSelect({ ...params, cast: false }) + getLocationSelect({ ...paramsWithoutConfidenceAlert, cast: false }) ) - .replace(/{location}/g, getLocationSelect(params)) + .replace(/{location}/g, getLocationSelect(paramsWithoutConfidenceAlert)) .replace('{startDate}', startDate) .replace('{endDate}', endDate) - .replace('{WHERE}', getWHEREQuery({ ...params, dataset: 'viirs' })) + .replace( + '{WHERE}', + getWHEREQuery({ ...paramsWithoutConfidenceAlert, dataset: 'viirs' }) + ) ); return dataRequest.get(url).then((response) => ({ diff --git a/services/get-where-query.js b/services/get-where-query.js index 30dfdb734e..b00d854c68 100644 --- a/services/get-where-query.js +++ b/services/get-where-query.js @@ -13,6 +13,7 @@ export const getWHEREQuery = (params = {}) => { const allFilterOptions = forestTypes.concat(landCategories); const allowedParams = ALLOWED_PARAMS[params.dataset || 'annual']; const isTreeCoverDensity = dataset === 'treeCoverDensity'; + const isVIIRS = dataset === 'viirs'; const comparisonString = ' = '; let paramString = 'WHERE '; @@ -35,6 +36,15 @@ export const getWHEREQuery = (params = {}) => { paramKeys = paramKeys.filter((item) => item !== 'threshold'); } + /* + * Removing confidence_cat = 'false' from VIIRS request + * if the user selects 'all alerts' on the VIIRS layer, + * we don't want to add a new parameter to the query + */ + if (isVIIRS && !params?.confidenceToggle === 'false') { + paramKeys = paramKeys.filter((item) => item !== 'confidence'); + } + paramKeys.forEach((parameter, index) => { const isLastParameter = paramKeys.length - 1 === index; const hasFilterOption = ['forestType', 'landCategory'].includes(parameter); @@ -46,15 +56,12 @@ export const getWHEREQuery = (params = {}) => { const tableKey = filterOption && (filterOption.tableKey || filterOption.tableKeys[dataset || 'annual']); + let isNumericValue = isNumber(value); const paramKey = translateParameterKey(parameter, params); - if (parameter === 'adm0' && type === 'wdpa') { - isNumericValue = false; - } - - if (dataset === 'net_change') { + if ((parameter === 'adm0' && type === 'wdpa') || dataset === 'net_change') { isNumericValue = false; }