Skip to content

Commit ba23505

Browse files
committed
merge develop
2 parents a5b3121 + 14f99b5 commit ba23505

File tree

13 files changed

+221
-37
lines changed

13 files changed

+221
-37
lines changed

app/assets/stylesheets/components/home/_c-home-summary.scss

+1-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ $item-padding-screen-m: rem(40px);
104104
background-color: $grey-light;
105105
overflow: hidden;
106106

107-
&:before {
107+
&::before {
108108
content: "";
109109
position: absolute;
110110
left: rem(-1px);
@@ -183,7 +183,6 @@ $item-padding-screen-m: rem(40px);
183183

184184
@media screen and (max-width: $screen-m - 1px) {
185185
.c-home-summary-item__button {
186-
187186
.c-regular-button {
188187
width: rem(224px);
189188
}

app/javascript/components/charts/components/pie-chart-legend/pie-chart-legend-component.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class PieChartLegend extends PureComponent {
2222
{data.map((item, index) => {
2323
const value = `${formatNumber({
2424
num: item[config.key],
25-
unit: config.unit
25+
unit: item.unit ? item.unit : config.unit
2626
})}`;
2727
return (
2828
<li className="legend-item" key={index.toString()}>

app/javascript/components/widgets/components/widget/selectors.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { flattenObj } from 'utils/data';
44
import isEmpty from 'lodash/isEmpty';
55
import uniq from 'lodash/uniq';
66
import sortBy from 'lodash/sortBy';
7+
import range from 'lodash/range';
78

89
export const selectAllPropsAndState = (state, ownProps) => ownProps;
910
export const selectWidgetSettings = (state, { settings }) => settings;
@@ -67,9 +68,12 @@ export const getRangeYears = createSelector(
6768
(data, config) => {
6869
const { startYears, endYears, yearsRange } = config.options || {};
6970
if (!startYears || !endYears || isEmpty(data)) return null;
70-
const flatData = flattenObj(data);
71-
let years = data.years || [];
72-
if (years.length) {
71+
let years =
72+
data.years ||
73+
(yearsRange && range(yearsRange[0], yearsRange[1] + 1)) ||
74+
[];
75+
if (!years.length) {
76+
const flatData = flattenObj(data);
7377
Object.keys(flatData).forEach(key => {
7478
if (key.includes('year')) {
7579
years = years.concat(flatData[key]);

app/javascript/components/widgets/manifest.js

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import * as treeCoverLocated from './widgets/land-cover/tree-cover-located';
2828
import * as emissions from './widgets/climate/emissions';
2929
import * as emissionsDeforestation from './widgets/climate/emissions-deforestation';
3030
import * as woodyBiomass from './widgets/climate/whrc-biomass/';
31+
import * as emissionsPlantations from './widgets/climate/emissions-plantations';
3132
import * as futureCarbonGains from './widgets/climate/future-carbon-gains';
3233

3334
// Biodiversity
@@ -66,6 +67,7 @@ export default {
6667
emissions,
6768
emissionsDeforestation,
6869
woodyBiomass,
70+
emissionsPlantations,
6971
futureCarbonGains,
7072
// biodiversity
7173
// gladBiodiversity,

app/javascript/components/widgets/widgets/climate/emissions-deforestation/config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default {
1414
layers: ['b32a2f15-25e8-4ecc-98e0-68782ab1c0fe'],
1515
metaKey: 'widget_carbon_emissions_tree_cover_loss',
1616
dataType: 'loss',
17-
colors: 'emissions',
17+
colors: 'climate',
1818
sentences:
1919
'Between {startYear} and {endYear}, a total of {value} of {type} ({annualAvg} per year) was released into the atmosphere as a result of tree cover loss in {location}.'
2020
};

app/javascript/components/widgets/widgets/climate/emissions-deforestation/selectors.js

+33-28
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { yearTicksFormatter } from 'components/widgets/utils/data';
77
// get list data
88
const getData = state => (state.data && state.data.loss) || null;
99
const getSettings = state => state.settings || null;
10+
const getColors = state => state.colors;
1011
const getIndicator = state => state.indicator || null;
1112
const getLocationName = state => state.locationName || null;
1213
const getSentences = state => state.config && state.config.sentences;
@@ -30,36 +31,40 @@ export const parseData = createSelector(
3031
}
3132
);
3233

33-
export const parseConfig = createSelector([getSettings], settings => {
34-
const { unit } = settings;
35-
return {
36-
height: 250,
37-
xKey: 'year',
38-
yKeys: {
39-
bars: {
40-
[unit]: {
41-
fill: '#DF511E',
42-
background: false
34+
export const parseConfig = createSelector(
35+
[getSettings, getColors],
36+
(settings, colors) => {
37+
const { unit } = settings;
38+
const { loss } = colors;
39+
return {
40+
height: 250,
41+
xKey: 'year',
42+
yKeys: {
43+
bars: {
44+
[unit]: {
45+
fill: loss.main,
46+
background: false
47+
}
4348
}
44-
}
45-
},
46-
xAxis: {
47-
tickFormatter: yearTicksFormatter
48-
},
49-
tooltip: [
50-
{
51-
key: 'year'
5249
},
53-
{
54-
key: [unit],
55-
unit: 't',
56-
unitFormat: value => format('.3s')(value)
57-
}
58-
],
59-
unit: 't',
60-
unitFormat: value => format('.2s')(value)
61-
};
62-
});
50+
xAxis: {
51+
tickFormatter: yearTicksFormatter
52+
},
53+
tooltip: [
54+
{
55+
key: 'year'
56+
},
57+
{
58+
key: [unit],
59+
unit: 't',
60+
unitFormat: value => format('.3s')(value)
61+
}
62+
],
63+
unit: 't',
64+
unitFormat: value => format('.2s')(value)
65+
};
66+
}
67+
);
6368

6469
export const parseSentence = createSelector(
6570
[parseData, getSettings, getIndicator, getSentences, getLocationName],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { getAdmin } from 'services/forest-data';
2+
import axios from 'axios';
3+
import maxBy from 'lodash/maxBy';
4+
import range from 'lodash/range';
5+
6+
export default ({ params }) =>
7+
axios
8+
.all([
9+
getAdmin({ ...params }),
10+
getAdmin({ ...params, indicator: 'plantations' })
11+
])
12+
.then(
13+
axios.spread((admin, plantations) => {
14+
const adminData = admin.data && admin.data.data;
15+
const plantData = plantations.data && plantations.data.data;
16+
17+
const maxYear = Math.max(
18+
maxBy(adminData, 'year').year,
19+
maxBy(plantData, 'year').year
20+
);
21+
22+
return { adminData, plantData, years: range(2013, maxYear + 1) };
23+
})
24+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export default {
2+
widget: 'emissions-plantations',
3+
title: {
4+
initial: 'Biomass loss emissions in natural forest vs. plantations'
5+
},
6+
categories: ['climate'],
7+
types: ['country'],
8+
admins: ['adm0', 'adm1', 'adm2'],
9+
options: {
10+
startYears: true,
11+
endYears: true,
12+
thresholds: true,
13+
units: ['co2LossByYear', 'cLossByYear']
14+
},
15+
colors: 'climate',
16+
layers: ['b32a2f15-25e8-4ecc-98e0-68782ab1c0fe'],
17+
metaKey: 'tree_biomass_loss',
18+
sortOrder: {},
19+
sentences: {
20+
initial:
21+
'From {startYear} to {endYear}, a total of {emissions} of {variable} emissions were released from tree cover loss in {location} natural forests.'
22+
},
23+
whitelists: {
24+
indicators: ['plantations']
25+
}
26+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Component from 'components/widgets/components/widget-pie-chart-legend';
2+
import getData from './actions';
3+
import getProps from './selectors';
4+
import config from './config';
5+
import settings from './settings';
6+
7+
export { getData, getProps, Component, config, settings };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { createSelector, createStructuredSelector } from 'reselect';
2+
import isEmpty from 'lodash/isEmpty';
3+
import { formatNumber } from 'utils/format';
4+
5+
const getData = state => state.data;
6+
const getLocationName = state => state.locationName;
7+
const getColors = state => state.colors;
8+
const getSentences = state => state.config && state.config.sentences;
9+
const getTitle = state => state.config.title;
10+
const getSettings = state => state.settings;
11+
12+
export const parseData = createSelector(
13+
[getData, getColors, getSettings],
14+
(data, colors, settings) => {
15+
if (isEmpty(data)) return null;
16+
const { adminData, plantData } = data;
17+
const { loss } = colors;
18+
19+
const adminTotal = adminData
20+
.filter(d => d.year >= settings.startYear && d.year <= settings.endYear)
21+
.reduce((acc, next) => (next.emissions ? acc + next.emissions : acc), 0);
22+
23+
const plantTotal = plantData
24+
.filter(d => d.year >= settings.startYear && d.year <= settings.endYear)
25+
.reduce((acc, next) => (next.emissions ? acc + next.emissions : acc), 0);
26+
const totalArea = adminTotal + plantTotal;
27+
const parsedData = [
28+
{
29+
label: 'Natural forest',
30+
value:
31+
settings.unit === 'co2LossByYear'
32+
? adminTotal
33+
: adminTotal / (44 / 12),
34+
unit: 't',
35+
color: loss.main,
36+
percentage: adminTotal / totalArea * 100
37+
},
38+
{
39+
label: 'Plantations',
40+
value:
41+
settings.unit === 'co2LossByYear'
42+
? plantTotal
43+
: plantTotal / (44 / 12),
44+
unit: 't',
45+
color: loss.secondary,
46+
percentage: plantTotal / totalArea * 100
47+
}
48+
];
49+
return parsedData;
50+
}
51+
);
52+
53+
export const parseSentence = createSelector(
54+
[parseData, getLocationName, getSentences, getSettings],
55+
(parsedData, locationName, sentences, settings) => {
56+
if (!parsedData) return null;
57+
const { initial } = sentences;
58+
const { startYear, endYear } = settings;
59+
const plantationsPct = parsedData.find(d => d.label === 'Plantations')
60+
.percentage;
61+
const emissions = parsedData.find(d => d.label === 'Natural forest').value;
62+
63+
const params = {
64+
location: locationName !== 'global' ? `${locationName}'s` : locationName,
65+
percentage:
66+
plantationsPct < 0.1
67+
? '<0.1%'
68+
: formatNumber({ num: plantationsPct, unit: '%' }),
69+
emissions: formatNumber({ num: emissions, unit: 't' }),
70+
startYear,
71+
endYear,
72+
variable: settings.unit === 'co2LossByYear' ? 'CO₂' : 'carbon'
73+
};
74+
75+
return {
76+
sentence: initial,
77+
params
78+
};
79+
}
80+
);
81+
82+
export const parseTitle = createSelector([getTitle], title => title.initial);
83+
84+
export default createStructuredSelector({
85+
data: parseData,
86+
sentence: parseSentence,
87+
title: parseTitle
88+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default {
2+
forestType: 'ifl',
3+
threshold: 30,
4+
startYear: 2013,
5+
endYear: 2017,
6+
layers: ['forest2010', 'ifl_2013_deg'],
7+
unit: 'co2LossByYear'
8+
};

app/javascript/data/colors.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
},
2929
"climate": {
3030
"ramp": [ "#EDD093", "#BFBC35", "#007F53", "#123A33"],
31-
"density": "#895122"
31+
"density": "#895122",
32+
"loss": {
33+
"main": "#DF511E",
34+
"secondary": "#F9A000"
35+
}
3236
},
3337
"plantations": {
3438
"main": "#d67828",

app/javascript/services/forest-data.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ const SQL_QUERIES = {
4242
'SELECT fao.country, fao.forempl, fao.femempl, fao.usdrev, fao.usdexp, fao.gdpusd2012, fao.totpop1000, fao.year FROM table_7_economics_livelihood as fao WHERE fao.year = 2000 or fao.year = 2005 or fao.year = 2010 or fao.year = 9999',
4343
nonGlobalDatasets:
4444
'SELECT iso, polyname FROM data WHERE polyname IN ({indicators}) GROUP BY iso, polyname ORDER BY polyname, iso',
45-
globalLandCover: 'SELECT * FROM global_land_cover_adm2 WHERE {location}'
45+
globalLandCover: 'SELECT * FROM global_land_cover_adm2 WHERE {location}',
46+
admin:
47+
"SELECT polyname, year_data.year as year, SUM(year_data.area_loss) as area, SUM(year_data.emissions) as emissions from {dataset} WHERE {location} AND polyname = '{indicator}' AND thresh= {threshold} GROUP BY {grouping}"
4648
};
4749

4850
const getExtentYear = year =>
@@ -299,3 +301,18 @@ export const getGlobalLandCover = ({ adm0, adm1, adm2 }) => {
299301
);
300302
return request.get(url);
301303
};
304+
305+
export const getAdmin = ({ adm0, adm1, adm2, threshold, indicator }) => {
306+
const url = `${REQUEST_URL}${SQL_QUERIES.admin}`
307+
.replace('{location}', getLocationQuery(adm0, adm1, adm2))
308+
.replace('{threshold}', threshold)
309+
.replace('{dataset}', DATASET)
310+
.replace('{indicator}', getIndicator(indicator))
311+
.replace(
312+
'{grouping}',
313+
indicator
314+
? 'polyname, iso, nested(year_data.year)'
315+
: 'bound1, polyname, iso, nested(year_data.year)'
316+
);
317+
return request.get(url);
318+
};

0 commit comments

Comments
 (0)