Skip to content

Feature: global disclaimer to footer of widgets #3477

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

Merged
merged 3 commits into from
Jun 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion app/javascript/components/widgets/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import { createAction } from 'redux-actions';
import { createThunkAction } from 'utils/redux';
import isEqual from 'lodash/isEqual';
import pick from 'lodash/pick';
import groupBy from 'lodash/groupBy';
import { encodeStateForUrl, decodeUrlForState } from 'utils/stateToUrl';
import { getNonGlobalDatasets } from 'services/forest-data';
import { COUNTRY, EMBED } from 'pages/dashboards/router';
import * as WIDGETS from './manifest';

export const setWidgetSettings = createAction('setWidgetSettings');
export const setWidgetLoading = createAction('setWidgetLoading');
export const setWidgetData = createAction('setWidgetData');
export const settingsItemSelected = createAction('settingsItemSelected');
export const setGlobalData = createAction('setGlobalData');

export const getWidgetData = createThunkAction(
'getWidgetData',
Expand Down Expand Up @@ -72,12 +75,33 @@ export const setWidgetSettingsStore = createThunkAction(
}
);

export const getGlobalData = createThunkAction(
'getGlobalData',
() => dispatch => {
getNonGlobalDatasets().then(response => {
const { data } = response.data;
const groupedData = groupBy(data, 'polyname');
const nonGlobalDatasets = {};
Object.keys(groupedData).forEach(d => {
nonGlobalDatasets[d] = groupedData[d].length;
});
dispatch(
setGlobalData({
nonGlobalDatasets
})
);
});
}
);

export default {
setWidgetSettingsUrl,
setWidgetSettingsStore,
settingsItemSelected,
setWidgetData,
getWidgetData,
getGlobalData,
setWidgetLoading,
setWidgetSettings
setWidgetSettings,
setGlobalData
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';

import './styles.scss';

class WidgetFooter extends PureComponent {
render() {
const { statement } = this.props;

return statement ? (
<div className="c-widget-footer">{statement}</div>
) : null;
}
}

WidgetFooter.propTypes = {
statement: PropTypes.string
};

export default WidgetFooter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { createSelector } from 'reselect';
import compact from 'lodash/compact';

// get list data
const getSettings = state => state.settings || null;
const getType = state => state.config.type || null;
const getNonGlobalDatasets = state => state.nonGlobalDatasets || null;
const getIndicator = state => state.indicator || null;
const getForestType = state => state.forestType || null;
const getLandCategory = state => state.landCategory || null;
const getLocation = state => state.payload || null;

export const getNonGlobalIndicator = createSelector(
[
getIndicator,
getForestType,
getLandCategory,
getLocation,
getNonGlobalDatasets
],
(indicator, forestType, landCategory, location, datasets) => {
if (!datasets || location.type !== 'global' || !indicator) return null;
if (datasets[indicator.value]) {
return indicator;
} else if (datasets[forestType && forestType.value]) {
return forestType;
} else if (datasets[landCategory && landCategory.value]) {
return landCategory;
}
return null;
}
);

// get lists selected
export const getStatement = createSelector(
[getSettings, getType, getNonGlobalDatasets, getNonGlobalIndicator],
(settings, type, datasets, indicator) => {
if (!settings) return '';
const { extentYear, threshold } = settings;
const statements = compact([
extentYear ? `${extentYear} tree cover extent` : null,
threshold || threshold === 0 ? `>${threshold}% tree canopy` : null,
type === 'loss'
? 'these estimates do not take tree cover gain into account'
: null,
datasets && indicator
? `*${indicator.label.toLowerCase()} are available in ${
datasets[indicator.value]
} countries only`
: null
]);

return statements.join(' | ');
}
);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@import '~styles/settings.scss';

.c-widget-settings-statement {
.c-widget-footer {
margin-top: rem(10px);
font-size: 12px;
color: rgba($slate, 0.5);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { connect } from 'react-redux';

import { getStatement } from './widget-settings-statement-selectors';
import Component from './widget-settings-statement-component';
import { getStatement } from './selectors';
import Component from './component';

const mapStateToProps = (state, ownProps) => ({
statement: getStatement(ownProps)
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Button from 'components/ui/button';
import DynamicSentence from 'components/ui/dynamic-sentence';

import WidgetHeader from '../widget-header';
import WidgetSettingsStatement from '../widget-settings-statement';
import WidgetFooter from '../widget-footer';

import './styles.scss';

Expand All @@ -18,7 +18,6 @@ class Widget extends PureComponent {
widget,
currentLabel,
shareUrl,
settings,
config,
embed,
loading,
Expand Down Expand Up @@ -80,7 +79,7 @@ class Widget extends PureComponent {
/>
)}
</div>
<WidgetSettingsStatement settings={settings} type={config.type} />
<WidgetFooter {...this.props} />
{embed &&
(!query || (query && !query.hideGfw)) && (
<div className="embed-footer">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ const mapStateToProps = ({ widgets, location }, ownProps) => {
parsedConfig: parseConfig && parseConfig(selectorData),
sentence: getSentence && getSentence(selectorData),
shareUrl,
embedUrl
embedUrl,
...widgets.global
};
};

Expand Down
12 changes: 11 additions & 1 deletion app/javascript/components/widgets/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@ Object.keys(Widgets).forEach(key => {
});

export const initialState = {
global: {},
...widgets
};

const setGlobalData = (state, { payload }) => ({
...state,
global: {
...state.global,
...payload
}
});

const setWidgetLoading = (state, { payload }) => ({
...state,
[payload]: {
Expand Down Expand Up @@ -62,5 +71,6 @@ export default {
setWidgetSettings,
setWidgetLoading,
setWidgetData,
setWidgetActive
setWidgetActive,
setGlobalData
};
22 changes: 21 additions & 1 deletion app/javascript/components/widgets/widgets.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { createElement, PureComponent } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import colors from 'data/colors.json';

import Component from './component';
Expand Down Expand Up @@ -64,6 +67,23 @@ const mapStateToProps = (
};
};

class WidgetsContainer extends PureComponent {
componentDidMount() {
const { getGlobalData } = this.props;
getGlobalData();
}

render() {
return createElement(Component, {
...this.props
});
}
}

WidgetsContainer.propTypes = {
getGlobalData: PropTypes.func
};

export { actions, reducers, initialState };

export default connect(mapStateToProps, actions)(Component);
export default connect(mapStateToProps, actions)(WidgetsContainer);
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,13 @@ export const getSentence = createSelector(

const params = {
indicator: indicator && indicator.label.toLowerCase(),
location: currentLabel === 'global' ? 'globally' : currentLabel,
location:
currentLabel === 'global'
? {
value: 'globally',
tooltip: 'this dataset is available in certain countries'
}
: currentLabel,
startYear,
endYear,
loss:
Expand Down
7 changes: 6 additions & 1 deletion app/javascript/services/forest-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ const SQL_QUERIES = {
faoDeforestRank:
'WITH mytable AS (SELECT fao.country as iso, fao.name, fao.deforest * 1000 AS deforest, fao.humdef FROM table_1_forest_area_and_characteristics as fao WHERE fao.year = {year} AND deforest is not null), rank AS (SELECT deforest, iso, name from mytable ORDER BY mytable.deforest DESC) SELECT row_number() over () as rank, iso, name, deforest from rank',
faoEcoLive:
'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'
'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',
nonGlobalDatasets:
"SELECT iso, polyname FROM data WHERE polyname IN ('plantations', 'mining', 'primary_forest', 'landmark', 'plantations__mining', 'plantations__landmark', 'primary_forest__mining', 'primary_forest__landmark') GROUP BY iso, polyname ORDER BY polyname, iso"
};

const getExtentYear = year =>
Expand Down Expand Up @@ -277,3 +279,6 @@ export const getGainRanked = ({
.replace('{polyname}', getIndicator(forestType, landCategory));
return request.get(url);
};

export const getNonGlobalDatasets = () =>
request.get(`${REQUEST_URL}${SQL_QUERIES.nonGlobalDatasets}`);