This commit is contained in:
Andrey Bakhvalov 2018-10-22 17:47:43 +03:00
parent 1c548efc7e
commit 3d206fbdb0
10 changed files with 124 additions and 80 deletions

View File

@ -1,12 +1,5 @@
{
"parser": "babel-eslint",
"extends": ["airbnb"],
"plugins": ["import", "react"],
"env": {
"browser": true,
"node": true,
"jest": true
},
"extends": ["react-app", "airbnb"],
"rules": {
"arrow-parens": [
"warn",
@ -16,7 +9,6 @@
}
],
"comma-dangle": ["error", "never"],
"function-paren-newline": ["error", "consistent"],
"jsx-quotes": ["error", "prefer-single"],
"max-len": [
"error",
@ -27,13 +19,6 @@
}
],
"no-return-assign": "warn",
"no-underscore-dangle": [
"error",
{
"allowAfterThis": true,
"allow": ["_id"]
}
],
"quotes": ["error", "single"],
"react/button-has-type": "off",
"react/destructuring-assignment": "off",

View File

@ -78,7 +78,7 @@ BEGIN
sel_zones.locationid = trips_by_hour.pulocationid
AND cast(trips_by_hour.pickup_datetime AS DATE) >= date_from
AND cast(trips_by_hour.pickup_datetime AS DATE) <= date_to
AND ((extract (HOUR FROM trips_by_hour.pickup_datetime) = in_hour) OR (in_hour IS NULL))
AND ((extract (HOUR FROM trips_by_hour.pickup_datetime) = in_hour) OR (in_hour = -1))
)
GROUP BY
sel_zones.locationid

View File

@ -0,0 +1,13 @@
import React from 'react';
const CaptionElement = ({ date, localeUtils, locale }) => {
const months = localeUtils.getMonths(locale);
return (
<div className='DayPicker-Caption'>
{months[date.getMonth()]}
</div>
);
};
export default CaptionElement;

View File

@ -0,0 +1 @@
export { default } from './CaptionElement';

View File

@ -1,9 +1,9 @@
import styled from 'styled-components';
export default styled.div`
margin-bottom: 14px;
margin-bottom: 30px;
font-size: 16px;
line-height: 1.44;
color: #dadfee;
color: rgba(218,223,238,0.9);
`;

View File

@ -3,11 +3,16 @@ import DayPicker, { DateUtils } from 'react-day-picker';
import { debounce } from 'debounce';
import 'react-day-picker/lib/style.css';
import { JAN, DEC } from '../../../config/constants';
import dateConverter from '../../../utils/dateConverter';
import Container from './Container';
import Title from './Title';
import Description from './Description';
import Separator from './Separator';
import Range from './Range';
import DayPickerContainer from './DayPicker';
import CaptionElement from './CaptionElement';
import TimePicker from './TimePicker';
import AvgTime from './AvgTime';
import Input from './Input';
@ -27,7 +32,9 @@ class Filters extends PureComponent {
debounce(this.props.changeFilter('hour', e.target.value), 300);
};
dateConverter = date => date && `${date.getDate()}.${date.getMonth() + 1}`;
setAverageTime = () => {
this.props.changeFilter('hour', -1);
};
toggleDayPicker = () => {
this.setState(
@ -36,9 +43,11 @@ class Filters extends PureComponent {
};
render() {
const { range, hour } = this.props;
const { from, to } = range;
const { range: { from, to }, hour } = this.props;
const modifiers = { start: from, end: to };
const isAvgHour = hour === -1;
const dateFrom = dateConverter(from);
const dateTo = dateConverter(to);
return (
<Container>
@ -48,8 +57,9 @@ class Filters extends PureComponent {
<Description>
Conducted from an area
</Description>
<Separator />
<Range onClick={this.toggleDayPicker}>
{`${this.dateConverter(from)} ${this.dateConverter(to)}`}
{`${dateFrom} ${dateTo}`}
</Range>
{this.state.isDayPickerEnabled && (
<DayPickerContainer>
@ -58,26 +68,17 @@ class Filters extends PureComponent {
selectedDays={[from, { from, to }]}
modifiers={modifiers}
onDayClick={this.handleDayClick}
captionElement={({ date, localeUtils, locale }) => {
const months = localeUtils.getMonths(locale);
return (
<div className='DayPicker-Caption'>
{months[date.getMonth()]}
</div>
);
}}
initialMonth={new Date(2017, 0)}
fromMonth={new Date(2017, 0)}
toMonth={new Date(2017, 11)}
captionElement={CaptionElement}
initialMonth={JAN}
fromMonth={JAN}
toMonth={DEC}
/>
</DayPickerContainer>
)}
<TimePicker>
<AvgTime
isEnabled={hour === -1}
onClick={() => this.props.changeFilter('hour', -1)}
isEnabled={isAvgHour}
onClick={this.setAverageTime}
>
AVG
</AvgTime>
@ -89,7 +90,7 @@ class Filters extends PureComponent {
step='1'
onChange={this.changeTime}
/>
{hour !== -1 && (
{!isAvgHour && (
<div>
{`${hour}:00`}
</div>

View File

@ -0,0 +1,8 @@
import styled from 'styled-components';
export default styled.div`
height: 9px;
border-top: solid 1px rgba(87,94,119,0.9);
border-bottom: solid 1px rgba(87,94,119,0.9);
margin-bottom: 30px;
`;

View File

@ -1,6 +1,10 @@
import React, { PureComponent } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import { MAPBOX_STYLE, MAPBOX_TOKEN } from '../../config/constants';
import dateConverter from '../../utils/dateConverter';
import Container from './Container';
import Filters from './Filters';
@ -19,37 +23,33 @@ class Map extends PureComponent {
};
componentDidMount() {
mapboxgl.accessToken = 'pk.eyJ1IjoibWFydGlucHJvamVjdDEiLCJhIjoiY2ptdW93MXZrMDNjMTNrcGhmNTJ1ZGljdCJ9.9fC5LXUepNAYTKu8O162OA';
mapboxgl.accessToken = MAPBOX_TOKEN;
this.map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/martinproject1/cjnfxj6053wz32rq8r9sija4o'
style: MAPBOX_STYLE
});
this.nav = new mapboxgl.NavigationControl();
this.map.scrollZoom.disable();
this.map.addControl(this.nav, 'top-right');
this.map.on('load', this.mapOnLoad);
}
componentDidUpdate() {
const { range, hour } = this.state;
const { from, to } = range;
if (!from || !to) return;
const dateFrom = this.dateConverter(from);
const dateTo = this.dateConverter(to);
const queryParams = encodeURI(
`date_from=${dateFrom}&date_to=${dateTo}&hour=${hour}`
);
const queryParams = this.getQueryParams();
const newStyleUrl = `/tiles/rpc/public.get_trips.json?${queryParams}`;
const newStyle = this.map.getStyle();
newStyle.sources['public.get_trips'].url = `/tiles/rpc/public.get_trips.json?${queryParams}`;
newStyle.sources['public.get_trips'].url = newStyleUrl;
this.map.setStyle(newStyle);
}
mapOnLoad = () => {
const queryParams = this.getQueryParams();
this.map.addSource('public.get_trips', {
type: 'vector',
url: '/tiles/rpc/public.get_trips.json?date_from=01.01.2017&date_to=02.01.2017&hour=9'
url: `/tiles/rpc/public.get_trips.json?${queryParams}`
});
this.map.addLayer({
id: 'trips',
@ -59,39 +59,65 @@ class Map extends PureComponent {
paint: {
'fill-extrusion-height': [
'interpolate',
['exponential', 1.3],
['linear'],
['get', 'trips'],
17,
0,
10,
1204,
100,
2526,
200,
4738,
3,
30,
70,
70,
90,
150,
300,
300,
2500,
400,
6249,
600
8000,
600,
12000,
800,
20000,
1100,
30000,
1600,
55000,
2000,
76000,
3000
],
'fill-extrusion-color': [
'interpolate',
['exponential', 1.3],
['linear'],
['get', 'trips'],
0,
'#f2a8ff',
2,
'#f2a8ff',
15,
'#dc70ff',
26,
'#bc39fe',
540,
'#9202fd',
900,
'#6002c5'
'#fff0f0',
3,
'#ffdade',
70,
'#ffc4d1',
90,
'#ffaec9',
300,
'#ff98c5',
2500,
'#f982c5',
8000,
'#ee6cc8',
12000,
'#de58ce',
20000,
'#c847d7',
30000,
'#ab3ae1',
55000,
'#8233ed',
76000,
'#3434f9'
],
'fill-extrusion-opacity': 0.75
}
});
}, 'place-town');
};
changeFilter = (filter, value) => {
@ -101,12 +127,13 @@ class Map extends PureComponent {
}));
};
dateConverter = (date) => {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
getQueryParams = () => {
const { range: { from, to }, hour } = this.state;
return `${month}.${day}.${year}`;
const dateFrom = `${dateConverter(from)}.2017`;
const dateTo = `${dateConverter(to)}.2017`;
return encodeURI(`date_from=${dateFrom}&date_to=${dateTo}&hour=${hour}`);
};
render() {

4
src/config/constants.js Normal file
View File

@ -0,0 +1,4 @@
export const MAPBOX_TOKEN = 'pk.eyJ1IjoibWFydGlucHJvamVjdDEiLCJhIjoiY2ptdW93MXZrMDNjMTNrcGhmNTJ1ZGljdCJ9.9fC5LXUepNAYTKu8O162OA';
export const MAPBOX_STYLE = 'mapbox://styles/martinproject1/cjnfxj6053wz32rq8r9sija4o';
export const JAN = new Date(2017, 0);
export const DEC = new Date(2017, 11);

View File

@ -0,0 +1,5 @@
export default (date) => {
if (!date) return '';
return `${date.getDate()}.${date.getMonth() + 1}`;
};