Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FLAG-926] FAO reforestation widget #4734

Merged
merged 9 commits into from
Jan 17, 2024
17 changes: 11 additions & 6 deletions components/widgets/forest-change/fao-reforest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export default {
admins: ['global', 'adm0'],
settingsConfig: [
{
key: 'period',
key: 'yearRange',
label: 'period',
type: 'select',
clearable: false,
border: true,
},
],
chartType: 'rankedList',
Expand All @@ -25,17 +27,17 @@ export default {
sortOrder: {
forestChange: 8,
},
refetchKeys: ['period'],
refetchKeys: ['yearRange'],
colors: 'gain',
sentences: {
globalInitial:
'According to the FAO, the {location} rate of reforestation in {year} was {rate} per year.',
'According to the FAO, the {location} rate of reforestation in between {startYearRange} and {endYearRange} was {rate} per year.',
initial:
'According to the FAO, the rate of reforestation in {location} was {rate} per year in {year}.',
'According to the FAO, the rate of reforestation in {location} was {rate} per year between {startYearRange} and {endYearRange}.',
noReforest: 'No reforestation data in {location}.',
},
settings: {
period: 2010,
yearRange: '2015-2020',
unit: 'ha/year',
pageSize: 5,
page: 0,
Expand All @@ -44,8 +46,11 @@ export default {
getFAOReforest({ ...params }).then((response) => {
const data = response.data.rows;
const hasCountryData = (data.length && data.find((d) => d.iso)) || null;

return hasCountryData ? data : {};
}),
getDataURL: (params) => [getFAOReforest({ ...params, download: true })],
getDataURL: async (params) => [
await getFAOReforest({ ...params, download: true }),
],
getWidgetProps,
};
48 changes: 34 additions & 14 deletions components/widgets/forest-change/fao-reforest/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import findIndex from 'lodash/findIndex';
import sortBy from 'lodash/sortBy';
import { formatNumber } from 'utils/format';

const getData = (state) => state.data || null;
const getAdm0 = (state) => state.adm0 || null;
const getData = (state) => state.data;
const getAdm0 = (state) => state.adm0;
const getColors = (state) => state.colors || null;
const getLocationName = (state) => state.locationLabel || null;
const getPeriod = (state) => state.settings.period || null;
const getSettings = (state) => state.settings;
const getSentences = (state) => state.sentences;
const getTitle = (state) => state.title;

export const getSortedData = createSelector([getData], (data) => {
if (!data || !data.length) return null;

return sortBy(uniqBy(data, 'iso'), 'rate')
.reverse()
.map((d, i) => ({
Expand All @@ -27,22 +28,26 @@ export const parseData = createSelector(
(data, adm0, colors) => {
if (!data || !data.length) return null;
let dataTrimmed = data;

if (adm0) {
const locationIndex = findIndex(data, (d) => d.iso === adm0);
let trimStart = locationIndex - 2;
let trimEnd = locationIndex + 3;

if (locationIndex < 2) {
trimStart = 0;
trimEnd = 5;
}
if (locationIndex > data.length - 3) {
trimStart = data.length - 5;
trimEnd = data.length;

if (locationIndex > data?.length - 3) {
trimStart = data?.length - 5;
trimEnd = data?.length;
}
dataTrimmed = data.slice(trimStart, trimEnd);

dataTrimmed = data?.slice(trimStart, trimEnd);
}

return dataTrimmed.map((d) => ({
return dataTrimmed?.map((d) => ({
...d,
label: d.name,
color: colors.main,
Expand All @@ -52,28 +57,43 @@ export const parseData = createSelector(
);

export const parseSentence = createSelector(
[getSortedData, parseData, getPeriod, getSentences, getLocationName, getAdm0],
(sortedData, data, period, sentences, locationName, adm0) => {
[
getSortedData,
parseData,
getSettings,
getSentences,
getLocationName,
getAdm0,
],
(sortedData, data, settings, sentences, locationName, adm0) => {
if (!data || !data.length) return null;
const { initial, noReforest, globalInitial } = sentences;
const countryData = data.find((d) => adm0 === d.iso) || null;

const yearRangeSeparated = settings.yearRange.split('-');
const startYearRange = yearRangeSeparated[0];
const endYearRange = yearRangeSeparated[1];

let globalRate = 0;

Object.keys(sortedData).forEach((k) => {
globalRate += sortedData[k].rate;
});
const rate =
locationName === 'global' ? globalRate : countryData && countryData.value;

const rate = locationName === 'global' ? globalRate : countryData?.value;
const formatType = rate < 1 ? '.3r' : '.3s';

let sentence = globalInitial;

if (locationName !== 'global') {
sentence = countryData && countryData.value > 0 ? initial : noReforest;
}
const formatType = rate < 1 ? '.3r' : '.3s';

const params = {
location: locationName,
year: period,
year: settings.yearRange,
startYearRange,
endYearRange,
rate: formatNumber({
num: rate,
unit: 'ha',
Expand Down
31 changes: 21 additions & 10 deletions services/forest-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ const NEW_SQL_QUERIES = {
faoExtent:
'SELECT iso, country, "planted forest (ha)" AS planted_forest__ha, "primary (ha)" AS primary_forest__ha, "naturally regenerating forest (ha)" AS regenerated_forest__ha, "forest (ha)" AS fao_treecover__ha, "total land area (ha)" as area_ha FROM data WHERE {location} AND year = {year}',
faoReforest:
'SELECT country AS iso, name, year, reforest * 1000 AS reforestation__rate, forest*1000 AS fao_treecover_reforest__ha FROM table_1_forest_area_and_characteristics as fao WHERE fao.year = {period} AND reforest > 0 ORDER BY reforestation__rate DESC',
'SELECT iso, country AS name, year, "reforestation (ha per year)" AS reforestation__rate, "forest expansion (ha per year)" AS fao_treecover_reforest__ha FROM table_1_forest_area_and_characteristics as fao WHERE fao.year = {yearRange} AND "reforestation (ha per year)" > 0 ORDER BY reforestation__rate DESC',
faoReforestDownload:
'SELECT iso, country AS name, year, "reforestation (ha per year)" AS reforestation__rate FROM table_1_forest_area_and_characteristics as fao WHERE fao.year = {yearRange} AND "reforestation (ha per year)" > 0 ORDER BY reforestation__rate DESC',
faoDeforest:
'SELECT iso, country as name, "deforestation (ha per year)" as fao_treecover_deforest__ha, "reforestation (ha per year)" as fao_reforestation__ha, "forest expansion (ha per year)" as fao_expansion__ha, year FROM data where year = {yearRange}',
faoDeforestRank:
Expand Down Expand Up @@ -86,31 +88,40 @@ export const getFAOExtent = async ({ adm0, faoYear = 2020, download }) => {
return widgetData;
};

export const getFAOReforest = ({ period, download }) => {
const url = `/sql?q=${NEW_SQL_QUERIES.faoReforest}`.replace(
'{period}',
period
export const getFAOReforest = async ({ yearRange = '2015-2020', download }) => {
const target = download ? 'download/csv' : 'query/json';
const query = download
? NEW_SQL_QUERIES.faoReforestDownload
: NEW_SQL_QUERIES.faoReforest;
const url = `/dataset/fao_forest_change/v2020/${target}?sql=${query}`.replace(
/{yearRange}/g,
`'${yearRange}'`
);

if (download) {
return {
name: 'fao_treecover_reforestation__ha',
url: `${CARTO_API}${url}&format=csv`,
url: new URL(
`${window.location.origin}${PROXIES.DATA_API}${url}`
).toString(),
};
}

return cartoRequest.get(url).then((response) => ({
...response,
const response = await dataRequest.get(url);

const widgetData = {
data: {
rows: response.data.rows.map((o) => {
rows: response.data.map((o) => {
delete Object.assign(o, { rate: o.reforestation__rate })
.reforestation__rate;
delete Object.assign(o, { extent: o.fao_treecover_reforest__ha })
.fao_treecover_reforest__ha;
return o;
}),
},
}));
};

return widgetData;
};

export const getFAODeforest = async ({
Expand Down
Loading