Skip to content

Commit

Permalink
Add Impact Layers & Refactor App Redux Structure (#55)
Browse files Browse the repository at this point in the history
This PR adds Impact Layers.

It also significantly refactors the layer configuration interface for much better type safety, decent (but not 100% perfect) parsing of the config file for ensuring proper config definitions.

It removes Immutable.js state, since redux toolbox is already using Immer.js for state immutability under the hood, and they weren't playing well together.

Refactors where state lives by adding concept of layer-specific data in Redux along with async loaders.

Adds loading animation.
  • Loading branch information
bencpeters authored May 26, 2020
1 parent c7dd094 commit 69deaec
Show file tree
Hide file tree
Showing 42 changed files with 2,191 additions and 577 deletions.
9 changes: 7 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@
]
}
],
"no-unused-vars": ["error", { "argsIgnorePattern": "^props$" }],
"no-console": ["warn", { "allow": ["warn", "error"] }]
"no-console": ["warn", { "allow": ["warn", "error"] }],
"no-unused-vars": ["warn", {
"argsIgnorePattern": "^props$",
"ignoreRestSiblings": true
}],
"lines-between-class-members": "off",
"max-classes-per-file": "off"
},
"settings": {
"import/resolver": {
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ yarn-error.log*
.firebase/

# Editors
.vscode/
.vscode/
.idea/
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@turf/bbox": "^6.0.1",
"@turf/boolean-point-in-polygon": "^6.0.1",
"@turf/helpers": "^6.1.4",
"@types/d3": "^5.7.2",
"@types/geojson": "^7946.0.7",
"@types/jest": "^24.0.0",
"@types/lodash": "^4.14.149",
Expand All @@ -50,6 +54,7 @@
"@typescript-eslint/eslint-plugin": "^2.23.0",
"@typescript-eslint/parser": "^2.25.0",
"babel-eslint": "10.0.3",
"d3-fetch": "^1.1.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.4",
Expand All @@ -65,8 +70,8 @@
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^1.7",
"geojson": "^0.5.0",
"geotiff": "^1.0.0-beta.11",
"husky": "^4.2.3",
"immutable": "^4.0.0-rc.12",
"lint-staged": "^10.0.8",
"lodash": "^4.17.15",
"mapbox-gl": "^1.8.1",
Expand All @@ -81,7 +86,7 @@
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.0",
"redux": "^4.0.5",
"redux-async-initial-state": "^0.3.0",
"reflect-metadata": "^0.1.13",
"typescript": "~3.8.2",
"url": "^0.11.0",
"xml-js": "^1.6.11"
Expand Down
2 changes: 2 additions & 0 deletions src/components/MapView/DateSelector/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { store } from '../../../context/store';
test('renders as expected', () => {
const realDateNow = Date.now.bind(global.Date);
const dateNowStub = jest.fn(() => 1530518207007);
// eslint-disable-next-line fp/no-mutation
global.Date.now = dateNowStub;

const { container } = render(
Expand All @@ -17,5 +18,6 @@ test('renders as expected', () => {
);
expect(container).toMatchSnapshot();

// eslint-disable-next-line fp/no-mutation
global.Date.now = realDateNow;
});
14 changes: 3 additions & 11 deletions src/components/MapView/DateSelector/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useState, useEffect, Fragment, forwardRef, Ref } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import moment from 'moment';
import { Map } from 'immutable';
import {
Divider,
Grid,
Expand All @@ -18,13 +17,11 @@ import {
faAngleDoubleLeft,
} from '@fortawesome/free-solid-svg-icons';
import 'react-datepicker/dist/react-datepicker.css';

import {
dateRangeSelector,
updateDateRange,
} from '../../../context/mapStateSlice';
import { months, getMonthStartAndEnd, isAvailableMonth } from './utils';
import { AvailableDates } from '../../../config/types';

interface InputProps {
value?: string;
Expand All @@ -41,7 +38,7 @@ const Input = forwardRef(
},
);

function DateSelector({ availableDates = Map(), classes }: DateSelectorProps) {
function DateSelector({ availableDates = [], classes }: DateSelectorProps) {
const dispatch = useDispatch();
const { startDate: stateStartDate } = useSelector(dateRangeSelector);
const stateStartDateYear = moment(stateStartDate).year();
Expand Down Expand Up @@ -91,12 +88,7 @@ function DateSelector({ availableDates = Map(), classes }: DateSelectorProps) {
showYearDropdown
dropdownMode="select"
customInput={<Input />}
includeDates={
availableDates
.valueSeq()
.flatten()
.toJS() as Date[]
}
includeDates={availableDates.map(d => new Date(d))}
/>
</Grid>

Expand Down Expand Up @@ -183,7 +175,7 @@ const styles = (theme: Theme) =>
});

export interface DateSelectorProps extends WithStyles<typeof styles> {
availableDates?: AvailableDates;
availableDates: number[];
}

export default withStyles(styles)(DateSelector);
14 changes: 5 additions & 9 deletions src/components/MapView/DateSelector/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import moment from 'moment';
import { List } from 'immutable';
import { AvailableDates } from '../../../config/types';

export const months = [
'Jan',
Expand Down Expand Up @@ -42,12 +40,10 @@ export function getMonthStartAndEnd(month: number, year: number) {
export function findAvailableDayInMonth(
month: number,
year: number,
availableDates: AvailableDates,
availableDates: number[],
) {
const date = new Date(year, month);
const filterDates = (dates: List<number>) =>
dates.filter(dateIt => moment(dateIt).isSame(date, 'month'));
return availableDates.map(filterDates).filter(layerDates => layerDates.size);
const reference = new Date(year, month);
return availableDates.filter(d => moment(d).isSame(reference, 'month'));
}

/**
Expand All @@ -60,7 +56,7 @@ export function findAvailableDayInMonth(
export function isAvailableMonth(
month: number,
year: number,
availableDates: AvailableDates,
availableDates: number[],
) {
return !findAvailableDayInMonth(month, year, availableDates).isEmpty();
return findAvailableDayInMonth(month, year, availableDates).length > 0;
}
70 changes: 0 additions & 70 deletions src/components/MapView/GroundstationLayers/index.tsx

This file was deleted.

60 changes: 60 additions & 0 deletions src/components/MapView/Layers/GroundstationLayer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useEffect } from 'react';
import { get } from 'lodash';
import { GeoJSONLayer } from 'react-mapbox-gl';
import * as MapboxGL from 'mapbox-gl';
import { useSelector, useDispatch } from 'react-redux';
import { legendToStops } from '../layer-utils';
import { GroundstationLayerProps } from '../../../../config/types';
import { layerDataSelector } from '../../../../context/mapStateSlice';
import {
LayerData,
loadLayerData,
} from '../../../../context/layers/layer-data';

function onClickCircle(evt: any) {
// eslint-disable-next-line
console.log(
get(evt.features[0], 'properties.index'),
get(evt.features[0], 'properties.aimagname'),
get(evt.features[0], 'properties.sumname'),
get(evt.features[0], 'properties.rasterheight'),
);
}

function GroundstationLayers({ layer }: { layer: GroundstationLayerProps }) {
const layerData = useSelector(layerDataSelector(layer.id)) as
| LayerData<GroundstationLayerProps>
| undefined;
const dispatch = useDispatch();

const { data } = layerData || {};

useEffect(() => {
if (!data) {
dispatch(loadLayerData({ layer }));
}
}, [data, dispatch, layer]);

if (!data) {
return null;
}

const circleLayout: MapboxGL.CircleLayout = { visibility: 'visible' };
const circlePaint: MapboxGL.CirclePaint = {
'circle-color': {
property: 'rasterheight',
stops: legendToStops(layer.legend),
},
};

return (
<GeoJSONLayer
data={data}
circleLayout={circleLayout}
circlePaint={circlePaint}
circleOnClick={onClickCircle}
/>
);
}

export default GroundstationLayers;
Loading

0 comments on commit 69deaec

Please sign in to comment.