Skip to content

Commit

Permalink
Merge pull request #4859 from wri/FLAG-1145-support-legend-in-bar-cha…
Browse files Browse the repository at this point in the history
…rt-widgets

[FLAG-1145][FLAG-1110] Support legend in bar chart widgets + add legend primary forest loss widget
  • Loading branch information
SARodrigues authored Oct 28, 2024
2 parents 9ea1916 + 55ba6af commit 8186945
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 2 deletions.
2 changes: 1 addition & 1 deletion components/charts/composed-chart/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const XAxisTickWithoutGap = ({ x, y, payload }) => {
</g>
);

/*
/*
Work around to show number 100 in the end of X axis in the chart
since the Data API sends 0 to 90 percent in the tree cover density widget
0 stands to 0%-9% as 90 stands to 90%-99%
Expand Down
3 changes: 3 additions & 0 deletions components/widget/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Widget extends PureComponent {
title: PropTypes.string.isRequired,
type: PropTypes.string,
active: PropTypes.bool,
analysis: PropTypes.bool,
downloadDisabled: PropTypes.bool,
filterSelected: PropTypes.bool,
maxSize: PropTypes.number,
Expand Down Expand Up @@ -85,6 +86,7 @@ class Widget extends PureComponent {
colors,
type,
active,
analysis,
downloadDisabled,
filterSelected,
maxSize,
Expand Down Expand Up @@ -218,6 +220,7 @@ class Widget extends PureComponent {
large={large}
autoHeight={autoHeight}
embed={embed}
analysis={analysis}
location={location}
locationName={locationLabelFull}
active={active}
Expand Down
78 changes: 78 additions & 0 deletions components/widget/components/widget-chart-legend/component.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';

import cx from 'classnames';

class WidgetChartLegend extends PureComponent {
render() {
const { className, vertical = false, data = {} } = this.props;
const { columns = [] } = data;

const anyColumnsHaveTitle = !!columns.find((column) => column.title);

return (
<div className={cx('c-widget-chart-legend', className, { vertical })}>
{columns.map(({ title, items }, columnIdx) => {
return (
<div key={columnIdx} className="c-widget-chart-legend__column">
{title && (
<span className="c-widget-chart-legend__column-title">
{title}
</span>
)}
<ul
className={cx('c-widget-chart-legend__column-items', {
padded: anyColumnsHaveTitle && !title,
})}
>
{items.map(({ label, color, dashline }, titleIdx) => {
return (
<li
key={titleIdx}
className="c-widget-chart-legend__column-item"
>
{dashline ? (
<span
className="c-widget-chart-legend__column-item--dashline"
style={{
borderColor: color,
}}
/>
) : (
<span
className="c-widget-chart-legend__column-item--circle"
style={{
backgroundColor: color,
}}
/>
)}
<p>{label}</p>
</li>
);
})}
</ul>
</div>
);
})}
</div>
);
}
}

WidgetChartLegend.propTypes = {
className: PropTypes.string,
vertical: PropTypes.bool,
data: {
columns: {
title: PropTypes.string,
items: PropTypes.arrayOf(
PropTypes.shape({
color: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
})
),
},
},
};

export default WidgetChartLegend;
3 changes: 3 additions & 0 deletions components/widget/components/widget-chart-legend/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Component from './component';

export default Component;
81 changes: 81 additions & 0 deletions components/widget/components/widget-chart-legend/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
@import '~styles/settings.scss';

.c-widget-chart-legend {
display: flex;
margin: 20px 0 0;
width: 100%;
gap: 60px;

&__column {
&-title {
display: block;
font-weight: 500;
font-size: rem(13px);
margin: 0 0 rem(8px) 0;
}

&-items {
display: flex;
flex-direction: column;
gap: 5px;

&.padded {
padding-top: rem(2px);
}
}

&-item {
font-size: rem(12px);
display: flex;

&--circle,
&--dashline {
display: inline-block;
width: rem(12px);
min-width: rem(12px);
min-height: rem(12px);
height: rem(12px);
margin-right: rem(7px);
}

&--circle {
border-radius: 100%;
align-self: flex-start;
margin-top: 1px;
}

&--dashline {
border-radius: 0;
border: none;
border-top: 2px dotted;
align-self: center;
transform: translateY(4px);
}

p {
color: $slate;
font-size: rem(12px);
line-height: 1.4;
}
}
}

&.vertical {
flex-direction: column;
gap: 5px;

.c-widget-chart-legend {
&__column {
&-title {
margin-top: rem(8px);
}

&-items {
&.padded {
padding-top: 0;
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import debounce from 'lodash/debounce';
import ComposedChart from 'components/charts/composed-chart';
import Brush from 'components/charts/brush-chart';
import Legend from 'components/charts/components/chart-legend';
import ChartLegend from '../widget-chart-legend';

class WidgetComposedChart extends Component {
static propTypes = {
analysis: PropTypes.bool,
originalData: PropTypes.array,
data: PropTypes.array,
config: PropTypes.object,
Expand Down Expand Up @@ -63,6 +65,7 @@ class WidgetComposedChart extends Component {

render() {
const {
analysis,
originalData,
data,
config,
Expand All @@ -72,7 +75,7 @@ class WidgetComposedChart extends Component {
barBackground,
toggleSettingsMenu,
} = this.props;
const { brush, legend } = config;
const { brush, legend, chartLegend } = config;
const showLegendSettingsBtn =
settingsConfig &&
settingsConfig.some((conf) => conf.key === 'compareYear');
Expand Down Expand Up @@ -107,6 +110,8 @@ class WidgetComposedChart extends Component {
onBrushEnd={this.handleBrushEnd}
/>
)}

{chartLegend && <ChartLegend data={chartLegend} vertical={analysis} />}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,25 @@ export const parseConfig = createSelector(
})
.reverse()
);

// Example on how to add columns & titles to the Chart Legend
// See: https://gfw.atlassian.net/browse/FLAG-1145
// const chartLegend = {
// columns: [
// {
// items: ['Wildfire', 'Forestry', 'Shifting agriculture']?.map(
// (name) => ({ label: name, color: categoryColors[name] })
// ),
// },
// {
// title: 'Drivers of permanent deforestation',
// items: ['Commodity driven deforestation', 'Urbanization']?.map(
// (name) => ({ label: name, color: categoryColors[name] })
// ),
// },
// ],
// };

const insertIndex = findIndex(tooltip, { key: 'class_Urbanization' });
if (insertIndex > -1) {
tooltip.splice(insertIndex, 0, {
Expand All @@ -181,6 +200,7 @@ export const parseConfig = createSelector(
formatNumber({ num: value, specialSpecifier: '.2s', spaceUnit: true }),
unit: 'tCO2e',
tooltip,
// chartLegend,
};
}
);
Expand Down
3 changes: 3 additions & 0 deletions components/widgets/component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Widgets extends PureComponent {
setMapSettings: PropTypes.func.isRequired,
handleClickWidget: PropTypes.func.isRequired,
embed: PropTypes.bool,
analysis: PropTypes.bool,
dashboard: PropTypes.bool,
groupBySubcategory: PropTypes.bool,
modalClosing: PropTypes.bool,
Expand Down Expand Up @@ -60,6 +61,7 @@ class Widgets extends PureComponent {
groupBySubcategory = false,
embed,
dashboard,
analysis,
simple,
modalClosing,
noDataMessage,
Expand Down Expand Up @@ -112,6 +114,7 @@ class Widgets extends PureComponent {
authenticated={authenticated}
active={activeWidget && activeWidget.widget === w.widget}
embed={embed}
analysis={analysis}
dashboard={dashboard}
simple={simple}
location={location}
Expand Down
17 changes: 17 additions & 0 deletions components/widgets/forest-change/tree-loss-primary/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,23 @@ const parseConfig = createSelector([getColors], (colors) => ({
color: colors.primaryForestLoss,
},
],
chartLegend: {
columns: [
{
items: [
{
label: 'Area of tree cover loss within 2001 primary forest extent',
color: colors.primaryForestLoss,
},
{
label: 'Percent of primary forest area in 2001 remaining',
color: colors.primaryForestExtent,
dashline: true,
},
],
},
],
},
}));

export const parseTitle = createSelector(
Expand Down
1 change: 1 addition & 0 deletions pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ import '../components/widget/styles.scss';
import '../components/widgets/styles.scss';
import '../components/widget/components/widget-alert/styles.scss';
import '../components/widget/components/widget-body/styles.scss';
import '../components/widget/components/widget-chart-legend/styles.scss';
import '../components/widget/components/widget-chart-and-list/styles.scss';
import '../components/widget/components/widget-chart-list/styles.scss';
import '../components/widget/components/widget-footer/styles.scss';
Expand Down

0 comments on commit 8186945

Please sign in to comment.