Skip to content

Commit

Permalink
Merge pull request #79 from NASA-IMPACT/develop
Browse files Browse the repository at this point in the history
v0.3.0
  • Loading branch information
olafveerman authored May 29, 2020
2 parents 92b3e94 + 0c4d740 commit 621bf2d
Show file tree
Hide file tree
Showing 49 changed files with 2,348 additions and 844 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
import * as d3 from 'd3';
import { css } from 'styled-components';
import { getDaysInMonth, add, getDate, startOfMonth } from 'date-fns';
import {
add,
getDaysInMonth,
getDate,
getHours,
startOfMonth,
startOfDay
} from 'date-fns';

import { themeVal } from '../../../styles/utils/general';

const roundDate = date => {
const days = getDaysInMonth(date);
const d = getDate(date);
return d >= days / 2
? startOfMonth(add(date, { months: 1 }))
: startOfMonth(date);
const roundDate = (date, interval) => {
if (interval === 'day') {
const h = getHours(date);
return h >= 12
? startOfDay(add(date, { days: 1 }))
: startOfDay(date);
} else {
const days = getDaysInMonth(date);
const d = getDate(date);
return d >= days / 2
? startOfMonth(add(date, { months: 1 }))
: startOfMonth(date);
}
};

const styles = props => css`
Expand All @@ -34,6 +48,8 @@ const styles = props => css`
export default {
styles,
init: ctx => {
const { timeUnit } = ctx.props;

const bisectorG = ctx.dataCanvas
.append('g')
.attr('class', 'bisector');
Expand All @@ -50,25 +66,31 @@ export default {
.style('fill', 'none')
.style('pointer-events', 'all')
.on('mouseover', function () {
const xPos = d3.mouse(this)[0];
const date = roundDate(ctx.xScale.invert(xPos), timeUnit);
const xPosSnap = ctx.xScale(date);
bisectorG.select('.bisector-interact').style('display', '');
ctx.onInternalAction('bisector.show', { date, x: xPosSnap });
})
.on('mouseout', function () {
bisectorG.select('.bisector-interact').style('display', 'none');
ctx.onInternalAction('bisector.hide');
})
.on('mousemove', function () {
const xPos = d3.mouse(this)[0];
const date = roundDate(ctx.xScale.invert(xPos));
const date = roundDate(ctx.xScale.invert(xPos), timeUnit);
const xPosSnap = ctx.xScale(date);
const { height } = ctx.getSize();
bisectorG.select('.bisector-interact')
.attr('y2', 0)
.attr('y1', height)
.attr('x1', xPosSnap)
.attr('x2', xPosSnap);
ctx.onInternalAction('bisector.move', { date, x: xPosSnap });
})
.on('click', function () {
const xPos = d3.mouse(this)[0];
const date = roundDate(ctx.xScale.invert(xPos));
const date = roundDate(ctx.xScale.invert(xPos), timeUnit);
ctx.props.onAction('date.set', { date });
});
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React from 'react';
import { createPortal } from 'react-dom';
import { PropTypes as T } from 'prop-types';
import styled from 'styled-components';
import { CSSTransition } from 'react-transition-group';
import * as d3 from 'd3';
import { rgba } from 'polished';
import { PropTypes as T } from 'prop-types';
import { format } from 'date-fns';

import SizeAwareElement from '../../common/size-aware-element';
import SizeAwareElement from '../size-aware-element';

import { themeVal, stylizeFunction } from '../../../styles/utils/general';
import { headingAlt } from '../../../styles/type/heading';
Expand All @@ -15,6 +18,7 @@ import dataExtentLayer from './data-extent.layer';
import bisectorLayer from './bisector.layer';
import xaxisLayer from './xaxis.layer';
import yaxisLayer from './yaxis.layer';
import Popover from './popover';

const _rgba = stylizeFunction(rgba);

Expand Down Expand Up @@ -50,10 +54,18 @@ const ChartWrapper = styled(SizeAwareElement)`
/* ${yaxisLayer.styles} */
`;

const formatDate = (date, interval) => {
if (interval === 'day') {
return format(date, 'dd MMMM yyyy');
} else {
return format(date, "MMMM yy''");
}
};

class DataBrowserChart extends React.Component {
constructor (props) {
super(props);
this.margin = { top: 16, right: 32, bottom: 40, left: 64 };
this.margin = { top: 16, right: 32, bottom: 40, left: 32 };
// Control whether the chart was rendered.
// The size aware element fires a onChange event once it is rendered
// But at that time the chart is not ready yet so we can't update the size.
Expand All @@ -64,6 +76,12 @@ class DataBrowserChart extends React.Component {
this.dataCanvas = null;

this.resizeListener = this.resizeListener.bind(this);

this.state = {
bisecting: false,
xPos: null,
xPosDate: null
};
}

componentDidMount () {
Expand All @@ -76,6 +94,29 @@ class DataBrowserChart extends React.Component {
this.updateChart();
}

onInternalAction (action, payload) {
switch (action) {
case 'bisector.show':
this.setState({
bisecting: true,
xPos: payload.x,
xPosDate: payload.date
});
break;
case 'bisector.hide':
this.setState({
bisecting: false
});
break;
case 'bisector.move':
this.setState({
xPos: payload.x,
xPosDate: payload.date
});
break;
}
}

resizeListener () {
if (!this.initialized) return;
this.updateChart();
Expand Down Expand Up @@ -152,20 +193,54 @@ class DataBrowserChart extends React.Component {
// yaxisLayer.update(this);
}

renderPopover () {
const { bisecting, xPos, xPosDate } = this.state;
if (!this.dataCanvas || !xPosDate) return;

const matrix = this.dataCanvas.node().getScreenCTM()
.translate(xPos, 0);

const posY = matrix.f;
const posX = matrix.e;

const style = {
left: posX + 'px',
top: posY + 'px'
};

return createPortal((
<CSSTransition
in={bisecting}
appear={true}
unmountOnExit={true}
classNames='pop-chart'
timeout={{ enter: 300, exit: 300 }}
>
<Popover style={style}>
{formatDate(xPosDate, this.props.timeUnit)}
</Popover>
</CSSTransition>
), document.querySelector('#app-container'));
}

render () {
return (
<ChartWrapper
swatch={this.props.swatch}
ref={el => {
this.container = el;
}}
onChange={this.resizeListener}
/>
<>
{this.renderPopover()}
<ChartWrapper
swatch={this.props.swatch}
ref={el => {
this.container = el;
}}
onChange={this.resizeListener}
/>
</>
);
}
}

DataBrowserChart.propTypes = {
timeUnit: T.string,
xDomain: T.array,
swatch: T.string
};
Expand Down
76 changes: 76 additions & 0 deletions app/assets/scripts/components/common/data-browser/popover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import styled, { css } from 'styled-components';
import { PropTypes as T } from 'prop-types';

import { themeVal } from '../../../styles/utils/general';
import { glsp } from '../../../styles/utils/theme-values';

const POPOVER_SHOW_HIDE_ANIM_TIME = 240;

const easeOutBack = 'cubic-bezier(0.175, 0.885, 0.32, 1.275)';
const easeInBack = 'cubic-bezier(0.6, -0.28, 0.735, 0.045)';

const popoverAnim = css`
&.pop-chart-appear,
&.pop-chart-enter {
transition: transform ${POPOVER_SHOW_HIDE_ANIM_TIME}ms ${easeOutBack}, opacity ${POPOVER_SHOW_HIDE_ANIM_TIME}ms ease-in-out;
transform: scale(0);
opacity: 0;
}
&.pop-chart-appear-active,
&.pop-chart-enter-active {
transform: scale(1);
opacity: 1;
}
&.pop-chart-exit {
transition: transform ${POPOVER_SHOW_HIDE_ANIM_TIME}ms ${easeInBack}, opacity ${POPOVER_SHOW_HIDE_ANIM_TIME}ms ease-in-out;
transform: scale(1);
opacity: 1;
}
&.pop-chart-exit-active {
transform: scale(0);
opacity: 0;
}
`;

const PopoverPositioner = styled.div`
position: absolute;
top: 0;
left: 0;
z-index: 1000;
pointer-events: none;
transform-origin: 0;
${popoverAnim}
`;

const PopoverSelf = styled.article`
border-radius: ${themeVal('shape.rounded')};
background-color: ${themeVal('color.surface')};
box-shadow: 0 0 8px 0 ${themeVal('color.baseAlphaC')};
padding: ${glsp(0.25, 0.5)};
transform: translate(-50%, -100%);
margin-top: -0.5rem;
`;

export default function Popover ({
children,
style,
...rest
}) {
return (
<PopoverPositioner style={style}>
<PopoverSelf {...rest}>
{children}
</PopoverSelf>
</PopoverPositioner>
);
}

Popover.propTypes = {
children: T.node,
style: T.object
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
PanelBlockTitle,
PanelBlockBody,
PanelBlockScroll
} from '../common/panel-block';
} from './panel-block';
import Layer from './layer';
import { Accordion } from '../common/accordion';
import { Accordion } from './accordion';

const PanelBlockLayer = styled(PanelBlock)`
flex: 2;
Expand Down Expand Up @@ -49,7 +49,7 @@ class DataLayersBlock extends React.Component {
onToggleClick={() => onAction('layer.toggle', l)}
onLegendKnobChange={(payload) => onAction('layer.legend-knob', { id: l.id, ...payload })}
knobPos={l.knobPos}
compareEnabled={get(l, 'compare.enabled')}
compareEnabled={!!l.compare}
compareActive={l.comparing}
compareHelp={get(l, 'compare.help')}
onCompareClick={() => onAction('layer.compare', l)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { PropTypes as T } from 'prop-types';
import styled from 'styled-components';
import { format } from 'date-fns';

import Dropdown from '../common/dropdown';
import Dropdown from './dropdown';
import Button from '../../styles/button/button';
import DateRange from '../common/date-range';
import DateRange from './date-range';

const DATE_FORMAT = 'MMM dd, yyyy';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ export default {
.merge(gradientStops)
// Update current.
.attr('offset', (d, i, all) => {
if (i === 0) return 0;
if (i === all.length - 1) return 1;
const count = all.length - 1;
const pointOriginalPosition = 1 / count * i;
return stopScale(pointOriginalPosition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { formatThousands } from '../../utils/format';
import Prose from '../../styles/type/prose';
import { FormSwitch } from '../../styles/form/switch';
import Button from '../../styles/button/button';
import { AccordionFold } from '../common/accordion';
import GradientChart from '../common/gradient-legend-chart/chart';
import { AccordionFold } from './accordion';
import GradientChart from './gradient-legend-chart/chart';

const makeGradient = (stops) => {
const d = 100 / stops.length - 1;
Expand Down
6 changes: 5 additions & 1 deletion app/assets/scripts/components/common/layers/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import no2 from './layer-no2';
import population from './layer-population';
import carCount from './layer-car-count';
import nightlights from './layer-nightlights';

export default [
no2,
population
population,
carCount,
nightlights
];
Loading

0 comments on commit 621bf2d

Please sign in to comment.