-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feat/limited-pfb-file-export
- Loading branch information
Showing
37 changed files
with
7,802 additions
and
1,734 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
.chart-carousel__container { | ||
width: 550px; | ||
padding: 10px 30px 30px 30px; // space for arrows and dots | ||
margin-left: 10px; | ||
margin-bottom: 10px; | ||
} | ||
|
||
.chart-carousel__container-border { | ||
box-shadow: 0 2px 4px rgba(0,0,0,0.3); | ||
} | ||
|
||
.chart-carousel__popup-chart { | ||
height: 50vh; | ||
} | ||
|
||
.chart-carousel__left-column { | ||
float: left; | ||
} | ||
|
||
.chart-carousel__description { | ||
text-align: justify; | ||
overflow-y: auto; | ||
height: 60vh; | ||
padding: 0 10px 0 20px; | ||
} | ||
|
||
.chart-carousel__image { | ||
max-width: 100%; | ||
max-height: 350px; | ||
margin: auto; | ||
} | ||
|
||
.chart-carousel__hover { | ||
position: absolute; | ||
left: 0; | ||
right: 0; | ||
margin: auto; | ||
background-color: white; | ||
box-shadow: 0 2px 4px rgba(0,0,0,0.3); | ||
max-width: 500px; | ||
padding: 10px; | ||
white-space: pre-wrap; | ||
z-index: 10; // place it over the "mapbox" link... | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import Slider from 'react-slick'; | ||
import 'slick-carousel/slick/slick.css'; | ||
import 'slick-carousel/slick/slick-theme.css'; | ||
|
||
import { covid19DashboardConfig } from '../../localconf'; | ||
import Spinner from '../../components/Spinner'; | ||
import PlotChart from '../PlotChart'; | ||
import './ChartCarousel.less'; | ||
|
||
|
||
class ChartCarousel extends PureComponent { | ||
constructor(props) { | ||
super(props); | ||
this.containerRef = React.createRef(); | ||
this.state = { | ||
hoveredChartId: null, | ||
hoverYPosition: 0, | ||
}; | ||
} | ||
|
||
onChartHover(hoveredChartId) { | ||
// match top of carousel component + 10 pixels | ||
const boundsRect = this.containerRef.current.getBoundingClientRect(); | ||
const topY = boundsRect.top + window.scrollY + 10; | ||
this.setState({ | ||
hoveredChartId, // if null, will not display hover info | ||
hoverYPosition: topY, | ||
}); | ||
} | ||
|
||
render() { | ||
if (!this.props.chartsConfig.length) { | ||
return null; | ||
} | ||
|
||
const sliderSettings = { | ||
dots: true, | ||
infinite: false, | ||
speed: 500, | ||
slidesToShow: 1, | ||
slidesToScroll: 1, | ||
arrows: true, | ||
}; | ||
|
||
const charts = []; | ||
this.props.chartsConfig.forEach((chartConfig, i) => { | ||
const hasImagePath = chartConfig.type === 'image' && chartConfig.path; | ||
|
||
// make sure the chart data is available as prop | ||
if (!(chartConfig.prop in this.props) && !hasImagePath && !chartConfig.guppyConfig) { | ||
console.error(`ChartCarousel is missing '${chartConfig.prop}' prop found in configuration`); // eslint-disable-line no-console | ||
return; | ||
} | ||
|
||
// generate the chart | ||
let chart = null; | ||
const plotChartConfig = { ...chartConfig, plots: this.props[chartConfig.prop] }; | ||
switch (chartConfig.type) { | ||
case 'component': | ||
chart = this.props[chartConfig.prop]; | ||
break; | ||
case 'image': | ||
chart = (<img | ||
className='chart-carousel__image' | ||
src={covid19DashboardConfig.dataUrl + | ||
(hasImagePath ? chartConfig.path : this.props[chartConfig.prop])} | ||
alt={`Chart${chartConfig.title ? ` for ${chartConfig.title}` : ''}`} | ||
/>); | ||
break; | ||
case 'lineChart': | ||
case 'barChart': | ||
chart = <PlotChart {...plotChartConfig} />; | ||
break; | ||
default: | ||
console.error(`ChartCarousel cannot handle '${chartConfig.type}' chart type found in configuration`); // eslint-disable-line no-console | ||
} | ||
|
||
// if the chart data is not loaded yet, do not display an empty chart | ||
if (!chart) { | ||
return; | ||
} | ||
|
||
// TODO: description scrollbar | ||
const showDescriptionColumn = this.props.isInPopup && ( | ||
chartConfig.title || chartConfig.description | ||
); | ||
const chartContainer = (<div | ||
key={0} | ||
onMouseOver={() => this.onChartHover(i)} | ||
onMouseOut={() => this.onChartHover(null)} | ||
> | ||
<div | ||
className={`${this.props.isInPopup ? 'chart-carousel__popup-chart' : null} ${showDescriptionColumn ? 'chart-carousel__left-column' : ''}`} | ||
> | ||
{chart} | ||
</div> | ||
{ showDescriptionColumn && | ||
<div className='chart-carousel__description'> | ||
<h3> | ||
{chartConfig.title} | ||
</h3> | ||
<p> | ||
{chartConfig.description} | ||
</p> | ||
</div> | ||
} | ||
</div>); | ||
charts.push(chartContainer); | ||
}); | ||
|
||
const showDescriptionHover = !this.props.isInPopup && | ||
this.state.hoveredChartId !== null && | ||
// do not show the hover if there is a title without | ||
// description - the title is already displayed | ||
this.props.chartsConfig[this.state.hoveredChartId].description; | ||
|
||
return ( | ||
charts.length > 0 ? | ||
<div> | ||
<div | ||
className={`chart-carousel__container ${this.props.isInPopup ? '' : 'chart-carousel__container-border'}`} | ||
ref={this.containerRef} | ||
// match the popup width... | ||
style={this.props.isInPopup ? { width: '70vw' } : {}} | ||
> | ||
<Slider {...sliderSettings}> | ||
{charts} | ||
</Slider> | ||
</div> | ||
|
||
{ showDescriptionHover && | ||
<div className='chart-carousel__hover' style={{ top: this.state.hoverYPosition }} > | ||
<h3> | ||
{this.props.chartsConfig[this.state.hoveredChartId].title} | ||
</h3> | ||
<p> | ||
{this.props.chartsConfig[this.state.hoveredChartId].description} | ||
</p> | ||
</div> | ||
} | ||
</div> | ||
: <Spinner /> | ||
); | ||
} | ||
} | ||
|
||
ChartCarousel.propTypes = { | ||
chartsConfig: PropTypes.array.isRequired, | ||
isInPopup: PropTypes.bool, | ||
}; | ||
|
||
ChartCarousel.defaultProps = { | ||
isInPopup: false, | ||
}; | ||
|
||
export default ChartCarousel; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
.control-panel { | ||
position: absolute; | ||
z-index: 2; | ||
padding: 8px; | ||
margin: 10px; | ||
max-width: 200px; | ||
height: fit-content; | ||
background: #fff; | ||
box-shadow: 0 2px 4px rgba(0,0,0,0.3); | ||
} | ||
|
||
.control-panel > * { | ||
margin-bottom: 0; | ||
} |
11 changes: 11 additions & 0 deletions
11
src/Covid19Dashboard/ControlPanel/LegendPanel/LegendPanel.less
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.legend-panel__item { | ||
margin-bottom: 0; | ||
} | ||
|
||
.legend-panel__item span { | ||
display: inline-block; | ||
width: 10px; | ||
height: 10px; | ||
margin-right: 5px; | ||
border: 1px solid black; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import React, { PureComponent } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import { numberWithCommas } from '../../dataUtils.js'; | ||
|
||
import './LegendPanel.less'; | ||
|
||
function dictToLegendList(colors) { | ||
// input: {0: '#FFF', 10: '#888', 100: '#000'} | ||
// output: [[ '0-9', '#FFF' ], [ '10-99', '#888' ], [ '100+', '#000' ]] | ||
return Object.entries(colors).map((value, i) => { | ||
const color = value[1]; | ||
let label = Number(value[0]); | ||
if (i === Object.keys(colors).length - 1) { | ||
label = `${label}+`; | ||
} else { | ||
const nextLabel = Number(Object.keys(colors)[i + 1]); | ||
if (nextLabel - 1 !== label) { | ||
label = `${label} - ${nextLabel - 1}`; | ||
} | ||
} | ||
return [numberWithCommas(label), color]; | ||
}); | ||
} | ||
|
||
class LegendPanel extends PureComponent { | ||
render() { | ||
const legendData = dictToLegendList(this.props.colors); | ||
return ( | ||
<div className='legend-panel'> | ||
<h3>Legend</h3> | ||
<div> | ||
{ | ||
legendData.map( | ||
value => | ||
(<p | ||
key={value[1]} | ||
className='legend-panel__item' | ||
> | ||
<span | ||
style={{ backgroundColor: value[1] }} | ||
/> | ||
{value[0]} | ||
</p>), | ||
) | ||
} | ||
</div> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
LegendPanel.propTypes = { | ||
colors: PropTypes.object, | ||
}; | ||
|
||
LegendPanel.defaultProps = { | ||
colors: {}, | ||
}; | ||
|
||
export default LegendPanel; |
3 changes: 3 additions & 0 deletions
3
src/Covid19Dashboard/ControlPanel/MapStylePanel/MapStylePanel.less
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.map-style-panel__radio { | ||
margin-right: 5px; | ||
} |
Oops, something went wrong.