From 6916991905cb1c056e48e8719a2963137f08ce23 Mon Sep 17 00:00:00 2001 From: akgupta89 Date: Sun, 19 Apr 2020 19:38:03 -0700 Subject: [PATCH 1/5] Converted to TypeScript --- frontend/package-lock.json | 64 ++++++++- frontend/package.json | 14 +- frontend/src/{App.test.js => App.test.tsx} | 0 frontend/src/{App.jsx => App.tsx} | 4 + .../src/{UIConstants.js => UIConstants.ts} | 0 frontend/src/actions/{index.js => index.ts} | 4 +- .../{AppBarLogo.jsx => AppBarLogo.tsx} | 0 .../{ControlPanel.jsx => ControlPanel.tsx} | 7 +- ...eRangeControl.jsx => DateRangeControl.tsx} | 18 +-- ...Controls.jsx => DateTimeRangeControls.tsx} | 0 ...dingIndicator.jsx => LoadingIndicator.tsx} | 0 .../{MapShield.jsx => MapShield.tsx} | 0 .../{MapSpider.jsx => MapSpider.tsx} | 20 ++- .../components/{MapStops.jsx => MapStops.tsx} | 15 +- .../{MareyChart.jsx => MareyChart.tsx} | 38 +++--- ...rt.jsx => OnTimePerformanceByDayChart.tsx} | 0 ...t.jsx => OnTimePerformanceByTimeChart.tsx} | 0 ...ram.jsx => OnTimePerformanceHistogram.tsx} | 0 ...ceStats.jsx => OnTimePerformanceStats.tsx} | 0 .../{QuadrantChart.jsx => QuadrantChart.tsx} | 0 .../{ReactSelect.jsx => ReactSelect.tsx} | 27 ++-- .../{RouteSummary.jsx => RouteSummary.tsx} | 0 .../{RouteTable.jsx => RouteTable.tsx} | 18 +-- ...art.jsx => ServiceFrequencyByDayChart.tsx} | 0 ...rt.jsx => ServiceFrequencyByTimeChart.tsx} | 0 ...m.jsx => ServiceFrequencyGapHistogram.tsx} | 0 ...gram.jsx => ServiceFrequencyHistogram.tsx} | 0 ...ncyStats.jsx => ServiceFrequencyStats.tsx} | 0 .../{SimpleChart.jsx => SimpleChart.tsx} | 2 +- ...eMarkChart.jsx => SimpleLineMarkChart.tsx} | 0 ...arChart.jsx => SimpleVerticalBarChart.tsx} | 0 ...tChart.jsx => SimpleVerticalRectChart.tsx} | 0 ...eDateControl.jsx => SingleDateControl.tsx} | 0 ...maryHeaderRow.jsx => SummaryHeaderRow.tsx} | 0 .../{SummaryRow.jsx => SummaryRow.tsx} | 0 .../{SummaryStats.jsx => SummaryStats.tsx} | 0 ...eRangeControl.jsx => TimeRangeControl.tsx} | 0 ...ravelTimeChart.jsx => TravelTimeChart.tsx} | 0 ...Histogram.jsx => TravelTimesHistogram.tsx} | 0 .../{TripSummary.jsx => TripSummary.tsx} | 0 ...ByDayChart.jsx => TripTimesByDayChart.tsx} | 4 +- ...TimeChart.jsx => TripTimesByTimeChart.tsx} | 4 +- ...{TripTimesStats.jsx => TripTimesStats.tsx} | 0 ...esHistogram.jsx => WaitTimesHistogram.tsx} | 8 +- frontend/src/{config.js => config.ts} | 2 +- .../src/helpers/{dateTime.js => dateTime.ts} | 0 .../helpers/{graphData.js => graphData.ts} | 0 .../{mapGeometry.js => mapGeometry.ts} | 0 ...teCalculations.js => routeCalculations.ts} | 0 frontend/src/{index.js => index.tsx} | 3 +- frontend/src/react-app-env.d.ts | 1 + frontend/src/reducers/{index.js => index.ts} | 0 .../{loadingReducer.js => loadingReducer.ts} | 0 frontend/src/reducers/{page.js => page.ts} | 2 +- .../{titleReducer.js => titleReducer.ts} | 2 +- frontend/src/{routesMap.js => routesMap.ts} | 16 ++- frontend/src/screens/{About.jsx => About.tsx} | 0 .../screens/{Dashboard.jsx => Dashboard.tsx} | 2 +- ...{DataDiagnostic.jsx => DataDiagnostic.tsx} | 2 +- frontend/src/screens/{Home.jsx => Home.tsx} | 0 .../screens/{Isochrone.jsx => Isochrone.tsx} | 129 +++++++++++------- .../screens/{NotFound.jsx => NotFound.tsx} | 0 .../{RouteScreen.jsx => RouteScreen.tsx} | 2 +- .../{serviceWorker.js => serviceWorker.ts} | 2 + frontend/src/store.js | 6 +- frontend/tsconfig.json | 22 +++ frontend/webpack.config.js | 20 ++- package-lock.json | 42 +++++- package.json | 6 + 69 files changed, 356 insertions(+), 150 deletions(-) rename frontend/src/{App.test.js => App.test.tsx} (100%) mode change 100755 => 100644 rename frontend/src/{App.jsx => App.tsx} (98%) mode change 100755 => 100644 rename frontend/src/{UIConstants.js => UIConstants.ts} (100%) rename frontend/src/actions/{index.js => index.ts} (99%) rename frontend/src/components/{AppBarLogo.jsx => AppBarLogo.tsx} (100%) rename frontend/src/components/{ControlPanel.jsx => ControlPanel.tsx} (98%) rename frontend/src/components/{DateRangeControl.jsx => DateRangeControl.tsx} (97%) rename frontend/src/components/{DateTimeRangeControls.jsx => DateTimeRangeControls.tsx} (100%) rename frontend/src/components/{LoadingIndicator.jsx => LoadingIndicator.tsx} (100%) rename frontend/src/components/{MapShield.jsx => MapShield.tsx} (100%) rename frontend/src/components/{MapSpider.jsx => MapSpider.tsx} (98%) rename frontend/src/components/{MapStops.jsx => MapStops.tsx} (98%) rename frontend/src/components/{MareyChart.jsx => MareyChart.tsx} (94%) rename frontend/src/components/{OnTimePerformanceByDayChart.jsx => OnTimePerformanceByDayChart.tsx} (100%) rename frontend/src/components/{OnTimePerformanceByTimeChart.jsx => OnTimePerformanceByTimeChart.tsx} (100%) rename frontend/src/components/{OnTimePerformanceHistogram.jsx => OnTimePerformanceHistogram.tsx} (100%) rename frontend/src/components/{OnTimePerformanceStats.jsx => OnTimePerformanceStats.tsx} (100%) rename frontend/src/components/{QuadrantChart.jsx => QuadrantChart.tsx} (100%) rename frontend/src/components/{ReactSelect.jsx => ReactSelect.tsx} (96%) rename frontend/src/components/{RouteSummary.jsx => RouteSummary.tsx} (100%) rename frontend/src/components/{RouteTable.jsx => RouteTable.tsx} (95%) rename frontend/src/components/{ServiceFrequencyByDayChart.jsx => ServiceFrequencyByDayChart.tsx} (100%) rename frontend/src/components/{ServiceFrequencyByTimeChart.jsx => ServiceFrequencyByTimeChart.tsx} (100%) rename frontend/src/components/{ServiceFrequencyGapHistogram.jsx => ServiceFrequencyGapHistogram.tsx} (100%) rename frontend/src/components/{ServiceFrequencyHistogram.jsx => ServiceFrequencyHistogram.tsx} (100%) rename frontend/src/components/{ServiceFrequencyStats.jsx => ServiceFrequencyStats.tsx} (100%) rename frontend/src/components/{SimpleChart.jsx => SimpleChart.tsx} (99%) rename frontend/src/components/{SimpleLineMarkChart.jsx => SimpleLineMarkChart.tsx} (100%) rename frontend/src/components/{SimpleVerticalBarChart.jsx => SimpleVerticalBarChart.tsx} (100%) rename frontend/src/components/{SimpleVerticalRectChart.jsx => SimpleVerticalRectChart.tsx} (100%) rename frontend/src/components/{SingleDateControl.jsx => SingleDateControl.tsx} (100%) rename frontend/src/components/{SummaryHeaderRow.jsx => SummaryHeaderRow.tsx} (100%) rename frontend/src/components/{SummaryRow.jsx => SummaryRow.tsx} (100%) rename frontend/src/components/{SummaryStats.jsx => SummaryStats.tsx} (100%) rename frontend/src/components/{TimeRangeControl.jsx => TimeRangeControl.tsx} (100%) rename frontend/src/components/{TravelTimeChart.jsx => TravelTimeChart.tsx} (100%) rename frontend/src/components/{TravelTimesHistogram.jsx => TravelTimesHistogram.tsx} (100%) rename frontend/src/components/{TripSummary.jsx => TripSummary.tsx} (100%) rename frontend/src/components/{TripTimesByDayChart.jsx => TripTimesByDayChart.tsx} (98%) rename frontend/src/components/{TripTimesByTimeChart.jsx => TripTimesByTimeChart.tsx} (98%) rename frontend/src/components/{TripTimesStats.jsx => TripTimesStats.tsx} (100%) rename frontend/src/components/{WaitTimesHistogram.jsx => WaitTimesHistogram.tsx} (98%) rename frontend/src/{config.js => config.ts} (95%) rename frontend/src/helpers/{dateTime.js => dateTime.ts} (100%) rename frontend/src/helpers/{graphData.js => graphData.ts} (100%) rename frontend/src/helpers/{mapGeometry.js => mapGeometry.ts} (100%) rename frontend/src/helpers/{routeCalculations.js => routeCalculations.ts} (100%) rename frontend/src/{index.js => index.tsx} (99%) mode change 100755 => 100644 create mode 100644 frontend/src/react-app-env.d.ts rename frontend/src/reducers/{index.js => index.ts} (100%) rename frontend/src/reducers/{loadingReducer.js => loadingReducer.ts} (100%) rename frontend/src/reducers/{page.js => page.ts} (91%) rename frontend/src/reducers/{titleReducer.js => titleReducer.ts} (88%) rename frontend/src/{routesMap.js => routesMap.ts} (93%) rename frontend/src/screens/{About.jsx => About.tsx} (100%) rename frontend/src/screens/{Dashboard.jsx => Dashboard.tsx} (96%) rename frontend/src/screens/{DataDiagnostic.jsx => DataDiagnostic.tsx} (94%) rename frontend/src/screens/{Home.jsx => Home.tsx} (100%) rename frontend/src/screens/{Isochrone.jsx => Isochrone.tsx} (89%) rename frontend/src/screens/{NotFound.jsx => NotFound.tsx} (100%) rename frontend/src/screens/{RouteScreen.jsx => RouteScreen.tsx} (98%) rename frontend/src/{serviceWorker.js => serviceWorker.ts} (99%) mode change 100755 => 100644 create mode 100644 frontend/tsconfig.json diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3adae244..547bfa58 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -4481,6 +4481,15 @@ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, + "@types/moment-timezone": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@types/moment-timezone/-/moment-timezone-0.5.13.tgz", + "integrity": "sha512-SWk1qM8DRssS5YR9L4eEX7WUhK/wc96aIr4nMa6p0kTk9YhGGOJjECVhIdPEj13fvJw72Xun69gScXSZ/UmcPg==", + "dev": true, + "requires": { + "moment": ">=2.14.0" + } + }, "@types/node": { "version": "12.12.31", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.31.tgz", @@ -5192,6 +5201,34 @@ "postcss-value-parser": "^4.0.3" } }, + "awesome-typescript-loader": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", + "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", + "requires": { + "chalk": "^2.4.1", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.1.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.3", + "webpack-log": "^1.2.0" + }, + "dependencies": { + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -12660,7 +12697,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, "requires": { "chalk": "^2.0.1" } @@ -12693,6 +12729,15 @@ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz", "integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==" }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -17364,6 +17409,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, + "source-map-loader": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", + "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", + "requires": { + "async": "^2.5.0", + "loader-utils": "^1.1.0" + } + }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", @@ -18444,6 +18498,12 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -18847,6 +18907,8 @@ "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", "optional": true, "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", "node-pre-gyp": "*" }, "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index 26ef5e58..7bb4cdd6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "@material-ui/lab": "^4.0.0-alpha.46", "@material-ui/styles": "^4.9.0", "@turf/turf": "^5.1.6", + "awesome-typescript-loader": "^5.2.1", "axios": "0.19.0", "clsx": "^1.1.0", "d3": "^5.15.0", @@ -31,9 +32,11 @@ "redux": "^4.0.5", "redux-first-router": "^2.1.5", "redux-first-router-link": "^2.1.1", - "redux-thunk": "^2.3.0" + "redux-thunk": "^2.3.0", + "source-map-loader": "^0.2.4" }, "devDependencies": { + "@types/moment-timezone": "^0.5.13", "babel-eslint": "10.1.0", "eslint": "^6.8.0", "eslint-config-airbnb": "^17.1.1", @@ -47,7 +50,8 @@ "eslint-plugin-react": "^7.19.0", "husky": "3.0.2", "lint-staged": "^8.2.1", - "prettier": "^1.19.1" + "prettier": "^1.19.1", + "typescript": "^3.8.3" }, "scripts": { "start": "react-scripts start", @@ -55,9 +59,9 @@ "test": "react-scripts test", "eject": "react-scripts eject", "heroku-postbuild": "npm build", - "lint": "eslint src --fix --ext .jsx,.js", - "lint:check": "eslint src --ext .jsx,.js", - "lint:all": "eslint --fix --ext src/**/*.{js,jsx}" + "lint": "eslint src --fix --ext .jsx,.js,.tsx,.ts", + "lint:check": "eslint src --ext .jsx,.js,.tsx,.ts", + "lint:all": "eslint --fix --ext src/**/*.{js,jsx,ts,tsx}" }, "eslintConfig": { "extends": "react-app" diff --git a/frontend/src/App.test.js b/frontend/src/App.test.tsx old mode 100755 new mode 100644 similarity index 100% rename from frontend/src/App.test.js rename to frontend/src/App.test.tsx diff --git a/frontend/src/App.jsx b/frontend/src/App.tsx old mode 100755 new mode 100644 similarity index 98% rename from frontend/src/App.jsx rename to frontend/src/App.tsx index efef5f24..2f3f4a63 --- a/frontend/src/App.jsx +++ b/frontend/src/App.tsx @@ -37,7 +37,11 @@ const Screens = { const theme = createMuiTheme({ breakpoints: { values: { + xs: 0, + sm: 600, md: 1050, + lg: 1280, + xl: 1920 }, }, palette: { diff --git a/frontend/src/UIConstants.js b/frontend/src/UIConstants.ts similarity index 100% rename from frontend/src/UIConstants.js rename to frontend/src/UIConstants.ts diff --git a/frontend/src/actions/index.js b/frontend/src/actions/index.ts similarity index 99% rename from frontend/src/actions/index.js rename to frontend/src/actions/index.ts index 8a113f35..fcc7b272 100644 --- a/frontend/src/actions/index.js +++ b/frontend/src/actions/index.ts @@ -222,7 +222,7 @@ query($agencyId:String!, $routeId:String!, const dates = computeDates(params.firstDateRange); return function(dispatch) { - const variables = { + const variables: { [key: string]: any } = { agencyId: params.agencyId, routeId: params.routeId, directionId: params.directionId, @@ -365,7 +365,7 @@ query($agencyId:String!, $routeId:String!, } }`.replace(/\s+/g, ' '); - const variables = { + const variables: { [key: string]: any } = { agencyId: Agencies[0].id, routeId: params.routeId, dates, diff --git a/frontend/src/components/AppBarLogo.jsx b/frontend/src/components/AppBarLogo.tsx similarity index 100% rename from frontend/src/components/AppBarLogo.jsx rename to frontend/src/components/AppBarLogo.tsx diff --git a/frontend/src/components/ControlPanel.jsx b/frontend/src/components/ControlPanel.tsx similarity index 98% rename from frontend/src/components/ControlPanel.jsx rename to frontend/src/components/ControlPanel.tsx index ada6933c..04ffd6e8 100644 --- a/frontend/src/components/ControlPanel.jsx +++ b/frontend/src/components/ControlPanel.tsx @@ -112,9 +112,8 @@ function ControlPanel(props) { const hoverStop = selectedRoute ? selectedRoute.stops[stopId] : null; - mapNode.style.setProperty( - '--stop-name', - `"${hoverStop ? hoverStop.title : ''}"`, + mapNode.setAttribute("style", + `--stop-name: "${hoverStop ? hoverStop.title : ''}"`, ); } } @@ -155,7 +154,7 @@ function ControlPanel(props) { const directionStops = selectedDirection ? selectedDirection.stops : []; - const labelStyle = { whiteSpace: 'nowrap' }; + const labelStyle: { [key: string]: any } = { whiteSpace: 'nowrap' }; return (
diff --git a/frontend/src/components/DateRangeControl.jsx b/frontend/src/components/DateRangeControl.tsx similarity index 97% rename from frontend/src/components/DateRangeControl.jsx rename to frontend/src/components/DateRangeControl.tsx index aa79e227..486df2cb 100644 --- a/frontend/src/components/DateRangeControl.jsx +++ b/frontend/src/components/DateRangeControl.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import Moment from 'moment'; -import { makeStyles } from '@material-ui/core/styles'; +import { createStyles, Theme, makeStyles } from '@material-ui/core/styles'; import Checkbox from '@material-ui/core/Checkbox'; import Divider from '@material-ui/core/Divider'; import Grid from '@material-ui/core/Grid'; @@ -35,7 +35,7 @@ import { initialGraphParams } from '../reducers'; import { fullQueryFromParams } from '../routesMap'; import { updateQuery } from '../actions'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles((theme: Theme) => ({ button: { textTransform: 'none', borderRadius: '0px', @@ -58,9 +58,9 @@ const useStyles = makeStyles(theme => ({ // color: theme.palette.text.secondary, textAlign: 'left', }, - column: { - flexGrow: '1', - }, + // column: { + // flexGrow: '1', + // }, dateTime: { whiteSpace: 'nowrap', display: 'flex', @@ -253,7 +253,7 @@ function DateRangeControl(props) { const newMoment = Moment(newDate); const startMoment = Moment(dateRangeParams.startDate); - const payload = { + const payload: { [key: string]: any } = { date: newDate, }; @@ -284,7 +284,7 @@ function DateRangeControl(props) { }; const setDateRange = daysBack => { - const date = initialGraphParams.date; + const date = initialGraphParams.firstDateRange.date; const startMoment = Moment(date).subtract(daysBack - 1, 'days'); // include end date updateLocalDateRangeParams({ @@ -391,7 +391,7 @@ function DateRangeControl(props) { .format('YYYY-MM-DD'), }, }} - className={classes.textField} + // className={classes.textField} InputLabelProps={{ shrink: true, }} @@ -412,7 +412,7 @@ function DateRangeControl(props) { max: maxDate, }, }} - className={classes.textField} + // className={classes.textField} InputLabelProps={{ shrink: true, }} diff --git a/frontend/src/components/DateTimeRangeControls.jsx b/frontend/src/components/DateTimeRangeControls.tsx similarity index 100% rename from frontend/src/components/DateTimeRangeControls.jsx rename to frontend/src/components/DateTimeRangeControls.tsx diff --git a/frontend/src/components/LoadingIndicator.jsx b/frontend/src/components/LoadingIndicator.tsx similarity index 100% rename from frontend/src/components/LoadingIndicator.jsx rename to frontend/src/components/LoadingIndicator.tsx diff --git a/frontend/src/components/MapShield.jsx b/frontend/src/components/MapShield.tsx similarity index 100% rename from frontend/src/components/MapShield.jsx rename to frontend/src/components/MapShield.tsx diff --git a/frontend/src/components/MapSpider.jsx b/frontend/src/components/MapSpider.tsx similarity index 98% rename from frontend/src/components/MapSpider.jsx rename to frontend/src/components/MapSpider.tsx index 0e5d2a08..05240fab 100644 --- a/frontend/src/components/MapSpider.jsx +++ b/frontend/src/components/MapSpider.tsx @@ -25,7 +25,6 @@ import { } from '../helpers/routeCalculations'; import { handleSpiderMapClick } from '../actions'; import { Agencies } from '../config'; - import MapShield from './MapShield'; const CLICK_RADIUS_MI = 0.5; // maximum radius for stops near a point @@ -40,8 +39,23 @@ function ValidLocationAlert(props) { ); } -class MapSpider extends Component { - constructor(props) { +interface Props { + [key: string]: any; +} + +interface State { + [key: string]: any; +} + +class MapSpider extends Component { + agency: any; + routeLayers: any[]; + mapRef: any; + boundUpdate: any; + onMouseOver: Function = (e: any) => {}; + onMouseOut: Function = (e: any) => {}; + + constructor(props: Props) { super(props); // for now, only supports 1 agency at a time. diff --git a/frontend/src/components/MapStops.jsx b/frontend/src/components/MapStops.tsx similarity index 98% rename from frontend/src/components/MapStops.jsx rename to frontend/src/components/MapStops.tsx index 91e6c89b..dc5775fa 100644 --- a/frontend/src/components/MapStops.jsx +++ b/frontend/src/components/MapStops.tsx @@ -13,8 +13,19 @@ import { handleGraphParams } from '../actions'; import { getTripPoints, getDistanceInMiles } from '../helpers/mapGeometry'; import { Agencies } from '../config'; -class MapStops extends Component { - constructor(props) { +interface Props { + [key: string]: any; +} + +interface State { + [key: string]: any; +} + +class MapStops extends Component { + agency: any; + boundUpdate: any; + + constructor(props: Props) { super(props); this.agency = Agencies[0]; diff --git a/frontend/src/components/MareyChart.jsx b/frontend/src/components/MareyChart.tsx similarity index 94% rename from frontend/src/components/MareyChart.jsx rename to frontend/src/components/MareyChart.tsx index 36284a92..6de8b850 100644 --- a/frontend/src/components/MareyChart.jsx +++ b/frontend/src/components/MareyChart.tsx @@ -3,7 +3,6 @@ /* Note: Importing MomentTZ adds new methods to Moment. MomentTZ is not meant to be used directly. */ import React, { Fragment, useState, useEffect } from 'react'; - import { XYPlot, HorizontalGridLines, @@ -16,21 +15,21 @@ import { Borders, } from 'react-vis'; import '../../node_modules/react-vis/dist/style.css'; - import { connect } from 'react-redux'; - import { Radio, FormControl, FormControlLabel } from '@material-ui/core'; - -import Moment from 'moment'; +import Moment from 'moment' +// eslint-disable-next-line import MomentTZ from 'moment-timezone/builds/moment-timezone-with-data-10-year-range'; // this augments Moment - import * as d3 from 'd3'; import { fetchArrivals } from '../actions'; import { getAgency } from '../config'; import { DWELL_THRESHOLD_SECS } from '../UIConstants'; - import { metersToMiles } from '../helpers/routeCalculations'; +interface Props { + [key: string]: any; +} + /** * Within state.arrivals.data, the data is organized as follows: * @@ -56,7 +55,7 @@ import { metersToMiles } from '../helpers/routeCalculations'; * * @param {Object} props */ -function MareyChart(props) { +const MareyChart: React.FC = (props: Props) => { const INBOUND_AND_OUTBOUND = 'Inbound_and_outbound'; const INBOUND = '1'; // same as directionInfo id const OUTBOUND = '0'; // same as directionInfo id @@ -64,10 +63,10 @@ function MareyChart(props) { const { graphParams, arrivals, arrivalsErr, routes, hidden } = props; const myFetchArrivals = props.fetchArrivals; - const [hintValue, setHintValue] = useState(); - const [tripHighlight, setTripHighlight] = useState(); - const [processedArrivals, setProcessedArrivals] = useState(); // where the tripData gets stored - const [selectedOption, setSelectedOption] = useState(INBOUND_AND_OUTBOUND); + const [hintValue, setHintValue] = useState(); + const [tripHighlight, setTripHighlight] = useState(); + const [processedArrivals, setProcessedArrivals] = useState(); // where the tripData gets stored + const [selectedOption, setSelectedOption] = useState(INBOUND_AND_OUTBOUND); const agency = getAgency(graphParams.agencyId); const timezoneId = agency ? agency.timezoneId : 'UTC'; @@ -137,7 +136,7 @@ function MareyChart(props) { } distance = metersToMiles(distance); - const arrivalMoment = Moment.unix(arrival.t).tz(timezoneId); + const arrivalMoment = Moment.unix(arrival.t).utcOffset(timezoneId); const yValue = (arrival.t - startTime) / 60 / 60 + startHourOfDay; // time of arrival in fractional hours myTripData.byTripId[tripId].series.push({ @@ -167,7 +166,7 @@ function MareyChart(props) { // so we can see the vehicle's exit in the data series. if (arrival.e - arrival.t > DWELL_THRESHOLD_SECS) { - const exitMoment = Moment.unix(arrival.e).tz(timezoneId); + const exitMoment = Moment.unix(arrival.e).utcOffset(timezoneId); const exitYValue = (arrival.e - startTime) / 60 / 60 + startHourOfDay; // time of arrival in fractional hours myTripData.byTripId[tripId].series.push({ @@ -200,10 +199,7 @@ function MareyChart(props) { const stops = myArrivals.stops; const startTime = myArrivals.start_time; - const startHourOfDay = Moment.unix(startTime) - .tz(timezoneId) - .hour(); - + const startHourOfDay = Moment.unix(startTime).utcOffset(timezoneId).hour(); const routeId = myArrivals.route_id; const route = myRoutes.find(myRoute => myRoute.id === routeId); @@ -373,7 +369,7 @@ function MareyChart(props) { control={ @@ -388,7 +384,7 @@ function MareyChart(props) { control={ @@ -403,7 +399,7 @@ function MareyChart(props) { control={ diff --git a/frontend/src/components/OnTimePerformanceByDayChart.jsx b/frontend/src/components/OnTimePerformanceByDayChart.tsx similarity index 100% rename from frontend/src/components/OnTimePerformanceByDayChart.jsx rename to frontend/src/components/OnTimePerformanceByDayChart.tsx diff --git a/frontend/src/components/OnTimePerformanceByTimeChart.jsx b/frontend/src/components/OnTimePerformanceByTimeChart.tsx similarity index 100% rename from frontend/src/components/OnTimePerformanceByTimeChart.jsx rename to frontend/src/components/OnTimePerformanceByTimeChart.tsx diff --git a/frontend/src/components/OnTimePerformanceHistogram.jsx b/frontend/src/components/OnTimePerformanceHistogram.tsx similarity index 100% rename from frontend/src/components/OnTimePerformanceHistogram.jsx rename to frontend/src/components/OnTimePerformanceHistogram.tsx diff --git a/frontend/src/components/OnTimePerformanceStats.jsx b/frontend/src/components/OnTimePerformanceStats.tsx similarity index 100% rename from frontend/src/components/OnTimePerformanceStats.jsx rename to frontend/src/components/OnTimePerformanceStats.tsx diff --git a/frontend/src/components/QuadrantChart.jsx b/frontend/src/components/QuadrantChart.tsx similarity index 100% rename from frontend/src/components/QuadrantChart.jsx rename to frontend/src/components/QuadrantChart.tsx diff --git a/frontend/src/components/ReactSelect.jsx b/frontend/src/components/ReactSelect.tsx similarity index 96% rename from frontend/src/components/ReactSelect.jsx rename to frontend/src/components/ReactSelect.tsx index 1c5a2c26..7594e7bd 100644 --- a/frontend/src/components/ReactSelect.jsx +++ b/frontend/src/components/ReactSelect.tsx @@ -13,7 +13,7 @@ const scrollHandlerDelay = 30; const theme = createMuiTheme({ palette: { background: { - focus: 'rgba(0, 0, 0, 0.05)', + // focus: 'rgba(0, 0, 0, 0.05)', }, }, }); @@ -21,7 +21,7 @@ const useStyles = makeStyles({ input: { display: 'flex', '&:focus': { - backgroundColor: theme.palette.background.focus, + // backgroundColor: theme.palette.background.focus, }, }, selectInput: { @@ -94,14 +94,13 @@ function Control(props) { ref={textRef} fullWidth InputProps={{ - inputComponent: 'div', - inputProps: { - children, - ...innerProps, - className: classes.input, - tabIndex: 0, - onKeyUp: handleTextKeyUp(props), - }, + inputComponent: () =>
}} label={textFieldProps.label} InputLabelProps={inputLabelProps} @@ -214,7 +213,7 @@ function Menu(props) { textFieldDOMRect, }, } = props; - const menuStyle = {}; + const menuStyle: { [key: string]: any } = {}; const timeout = menuTransition.current ? transitionDuration : 0; const [menuStyleRight, setMenuStyleRight] = useState(0); const [menuStyleBottom, setMenuStyleBottom] = useState(0); @@ -350,7 +349,7 @@ function Option(props) { data: { value }, selectProps: { onItemMouseOver, onItemMouseOut }, } = props; - const focusedStyle = {}; + const focusedStyle: { [key: string]: any } = {}; if (isFocused) { if (onItemMouseOver) { @@ -401,7 +400,9 @@ function handleMenuClose( return () => { allowTransition.current = true; - document.activeElement.blur(); + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } setMenuIsOpenTransition(false); setTimeout(() => setMenuIsOpen(false), transitionDuration); diff --git a/frontend/src/components/RouteSummary.jsx b/frontend/src/components/RouteSummary.tsx similarity index 100% rename from frontend/src/components/RouteSummary.jsx rename to frontend/src/components/RouteSummary.tsx diff --git a/frontend/src/components/RouteTable.jsx b/frontend/src/components/RouteTable.tsx similarity index 95% rename from frontend/src/components/RouteTable.jsx rename to frontend/src/components/RouteTable.tsx index 1cf3282b..8bee0eb0 100644 --- a/frontend/src/components/RouteTable.jsx +++ b/frontend/src/components/RouteTable.tsx @@ -1,15 +1,7 @@ import React, { useState, Fragment } from 'react'; import PropTypes from 'prop-types'; import { lighten, makeStyles, useTheme } from '@material-ui/core/styles'; -import Popover from '@material-ui/core/Popover'; -import Table from '@material-ui/core/Table'; -import TableBody from '@material-ui/core/TableBody'; -import TableCell from '@material-ui/core/TableCell'; -import TableHead from '@material-ui/core/TableHead'; -import TableRow from '@material-ui/core/TableRow'; -import TableSortLabel from '@material-ui/core/TableSortLabel'; -import IconButton from '@material-ui/core/IconButton'; - +import { Popover, Table, TableBody, TableCell, TableHead, TableRow, TableSortLabel, IconButton } from '@material-ui/core'; import InfoIcon from '@material-ui/icons/InfoOutlined'; import { connect } from 'react-redux'; import Navlink from 'redux-first-router-link'; @@ -77,7 +69,11 @@ function stableSort(array, sortOrder, orderBy) { return stabilizedThis.map(el => el[0]); } -function EnhancedTableHead(props) { +interface Props { + [key: string]: any; +} + +const EnhancedTableHead: React.FC = (props: Props) => { const { order, orderBy, onRequestSort, columns } = props; const createSortHandler = property => event => { onRequestSort(event, property); @@ -367,7 +363,7 @@ function RouteTable(props) { order={order} orderBy={orderBy} onRequestSort={handleRequestSort} - rowCount={displayedRouteStats.length} + // rowCount={displayedRouteStats.length} columns={columns} /> diff --git a/frontend/src/components/ServiceFrequencyByDayChart.jsx b/frontend/src/components/ServiceFrequencyByDayChart.tsx similarity index 100% rename from frontend/src/components/ServiceFrequencyByDayChart.jsx rename to frontend/src/components/ServiceFrequencyByDayChart.tsx diff --git a/frontend/src/components/ServiceFrequencyByTimeChart.jsx b/frontend/src/components/ServiceFrequencyByTimeChart.tsx similarity index 100% rename from frontend/src/components/ServiceFrequencyByTimeChart.jsx rename to frontend/src/components/ServiceFrequencyByTimeChart.tsx diff --git a/frontend/src/components/ServiceFrequencyGapHistogram.jsx b/frontend/src/components/ServiceFrequencyGapHistogram.tsx similarity index 100% rename from frontend/src/components/ServiceFrequencyGapHistogram.jsx rename to frontend/src/components/ServiceFrequencyGapHistogram.tsx diff --git a/frontend/src/components/ServiceFrequencyHistogram.jsx b/frontend/src/components/ServiceFrequencyHistogram.tsx similarity index 100% rename from frontend/src/components/ServiceFrequencyHistogram.jsx rename to frontend/src/components/ServiceFrequencyHistogram.tsx diff --git a/frontend/src/components/ServiceFrequencyStats.jsx b/frontend/src/components/ServiceFrequencyStats.tsx similarity index 100% rename from frontend/src/components/ServiceFrequencyStats.jsx rename to frontend/src/components/ServiceFrequencyStats.tsx diff --git a/frontend/src/components/SimpleChart.jsx b/frontend/src/components/SimpleChart.tsx similarity index 99% rename from frontend/src/components/SimpleChart.jsx rename to frontend/src/components/SimpleChart.tsx index 3af3596d..091cc466 100644 --- a/frontend/src/components/SimpleChart.jsx +++ b/frontend/src/components/SimpleChart.tsx @@ -11,7 +11,7 @@ import { } from 'react-vis'; import DiscreteColorLegend from 'react-vis/dist/legends/discrete-color-legend'; -function getDefaultYDomain(series) { +function getDefaultYDomain(series, stackBy) { let yMin = 0; let yMax = 0; diff --git a/frontend/src/components/SimpleLineMarkChart.jsx b/frontend/src/components/SimpleLineMarkChart.tsx similarity index 100% rename from frontend/src/components/SimpleLineMarkChart.jsx rename to frontend/src/components/SimpleLineMarkChart.tsx diff --git a/frontend/src/components/SimpleVerticalBarChart.jsx b/frontend/src/components/SimpleVerticalBarChart.tsx similarity index 100% rename from frontend/src/components/SimpleVerticalBarChart.jsx rename to frontend/src/components/SimpleVerticalBarChart.tsx diff --git a/frontend/src/components/SimpleVerticalRectChart.jsx b/frontend/src/components/SimpleVerticalRectChart.tsx similarity index 100% rename from frontend/src/components/SimpleVerticalRectChart.jsx rename to frontend/src/components/SimpleVerticalRectChart.tsx diff --git a/frontend/src/components/SingleDateControl.jsx b/frontend/src/components/SingleDateControl.tsx similarity index 100% rename from frontend/src/components/SingleDateControl.jsx rename to frontend/src/components/SingleDateControl.tsx diff --git a/frontend/src/components/SummaryHeaderRow.jsx b/frontend/src/components/SummaryHeaderRow.tsx similarity index 100% rename from frontend/src/components/SummaryHeaderRow.jsx rename to frontend/src/components/SummaryHeaderRow.tsx diff --git a/frontend/src/components/SummaryRow.jsx b/frontend/src/components/SummaryRow.tsx similarity index 100% rename from frontend/src/components/SummaryRow.jsx rename to frontend/src/components/SummaryRow.tsx diff --git a/frontend/src/components/SummaryStats.jsx b/frontend/src/components/SummaryStats.tsx similarity index 100% rename from frontend/src/components/SummaryStats.jsx rename to frontend/src/components/SummaryStats.tsx diff --git a/frontend/src/components/TimeRangeControl.jsx b/frontend/src/components/TimeRangeControl.tsx similarity index 100% rename from frontend/src/components/TimeRangeControl.jsx rename to frontend/src/components/TimeRangeControl.tsx diff --git a/frontend/src/components/TravelTimeChart.jsx b/frontend/src/components/TravelTimeChart.tsx similarity index 100% rename from frontend/src/components/TravelTimeChart.jsx rename to frontend/src/components/TravelTimeChart.tsx diff --git a/frontend/src/components/TravelTimesHistogram.jsx b/frontend/src/components/TravelTimesHistogram.tsx similarity index 100% rename from frontend/src/components/TravelTimesHistogram.jsx rename to frontend/src/components/TravelTimesHistogram.tsx diff --git a/frontend/src/components/TripSummary.jsx b/frontend/src/components/TripSummary.tsx similarity index 100% rename from frontend/src/components/TripSummary.jsx rename to frontend/src/components/TripSummary.tsx diff --git a/frontend/src/components/TripTimesByDayChart.jsx b/frontend/src/components/TripTimesByDayChart.tsx similarity index 98% rename from frontend/src/components/TripTimesByDayChart.jsx rename to frontend/src/components/TripTimesByDayChart.tsx index 2d7ed4a7..fca15ee7 100644 --- a/frontend/src/components/TripTimesByDayChart.jsx +++ b/frontend/src/components/TripTimesByDayChart.tsx @@ -99,7 +99,7 @@ function TripTimesByDayChart(props) { control={ diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.ts similarity index 100% rename from frontend/src/reducers/index.js rename to frontend/src/reducers/index.ts diff --git a/frontend/src/reducers/loadingReducer.js b/frontend/src/reducers/loadingReducer.ts similarity index 100% rename from frontend/src/reducers/loadingReducer.js rename to frontend/src/reducers/loadingReducer.ts diff --git a/frontend/src/reducers/page.js b/frontend/src/reducers/page.ts similarity index 91% rename from frontend/src/reducers/page.js rename to frontend/src/reducers/page.ts index 0bceaa2d..c1882a11 100644 --- a/frontend/src/reducers/page.js +++ b/frontend/src/reducers/page.ts @@ -26,5 +26,5 @@ export function typeForPage(page) { return currentType; } -export default (state = 'DASHBOARD', action = {}) => +export default (state = 'DASHBOARD', action: {type: string}) => components[action.type] || state; diff --git a/frontend/src/reducers/titleReducer.js b/frontend/src/reducers/titleReducer.ts similarity index 88% rename from frontend/src/reducers/titleReducer.js rename to frontend/src/reducers/titleReducer.ts index 66236204..afcff206 100644 --- a/frontend/src/reducers/titleReducer.js +++ b/frontend/src/reducers/titleReducer.ts @@ -2,7 +2,7 @@ import { APP_NAME } from '../UIConstants'; const DEFAULT = APP_NAME; -export default (state = DEFAULT, action = {}) => { +export default (state = DEFAULT, action: { type: string }) => { switch (action.type) { case 'DASHBOARD': return `Dashboard | ${DEFAULT}`; diff --git a/frontend/src/routesMap.js b/frontend/src/routesMap.ts similarity index 93% rename from frontend/src/routesMap.js rename to frontend/src/routesMap.ts index 8bc7fdd4..f5fddcb8 100644 --- a/frontend/src/routesMap.js +++ b/frontend/src/routesMap.ts @@ -7,6 +7,13 @@ export const START_DATE = 'startDate'; export const START_TIME = 'startTime'; export const END_TIME = 'endTime'; export const DAYS_OF_THE_WEEK = 'daysOfTheWeek'; +export interface DateRangeInterface { + startTime: any; + endTime: any; + date: string; + startDate: string; + daysOfTheWeek: any; +} /** * Gets the string values from a date range object within a query string. @@ -14,7 +21,7 @@ export const DAYS_OF_THE_WEEK = 'daysOfTheWeek'; * @param dateRangeQuery A query subobject representing a date range. * @returns A graphParams subobject representing a date range. */ -function processDateRangeQuery(dateRangeQuery) { +function processDateRangeQuery(dateRangeQuery): DateRangeInterface { const initialDateRangeParams = initialGraphParams.firstDateRange; if (!dateRangeQuery) { @@ -25,11 +32,12 @@ function processDateRangeQuery(dateRangeQuery) { // If the values are missing, we must use the defaults, in case the user is changing // from a nondefault to default value. - const newDateRangeParams = { + const newDateRangeParams: DateRangeInterface = { date: date || initialDateRangeParams.date, startDate: startDate || initialDateRangeParams.startDate, startTime: startTime || null, endTime: endTime || null, + daysOfTheWeek: null, }; if (daysOfTheWeek) { @@ -97,7 +105,7 @@ function processQuery(getState) { * @returns The query subobject. */ export function dateQueryFromDateRangeParams(params) { - const dateQuery = {}; + const dateQuery: { [key: string]: any } = {}; const initialDateRangeParams = initialGraphParams.firstDateRange; if (!params) { @@ -132,7 +140,7 @@ export function dateQueryFromDateRangeParams(params) { * @returns The query object to dispatch. */ export function fullQueryFromParams(params) { - const query = {}; + const query: { [key: string]: any } = {}; query.firstDateRange = dateQueryFromDateRangeParams(params.firstDateRange); query.secondDateRange = params.secondDateRange || undefined; return query; diff --git a/frontend/src/screens/About.jsx b/frontend/src/screens/About.tsx similarity index 100% rename from frontend/src/screens/About.jsx rename to frontend/src/screens/About.tsx diff --git a/frontend/src/screens/Dashboard.jsx b/frontend/src/screens/Dashboard.tsx similarity index 96% rename from frontend/src/screens/Dashboard.jsx rename to frontend/src/screens/Dashboard.tsx index 7b402fd7..ea887bdc 100644 --- a/frontend/src/screens/Dashboard.jsx +++ b/frontend/src/screens/Dashboard.tsx @@ -40,7 +40,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - fetchRoutes: params => dispatch(fetchRoutes(params)), + fetchRoutes: () => dispatch(fetchRoutes), handleGraphParams: params => dispatch(handleGraphParams(params)), }); diff --git a/frontend/src/screens/DataDiagnostic.jsx b/frontend/src/screens/DataDiagnostic.tsx similarity index 94% rename from frontend/src/screens/DataDiagnostic.jsx rename to frontend/src/screens/DataDiagnostic.tsx index 5ece560e..4d624f2e 100644 --- a/frontend/src/screens/DataDiagnostic.jsx +++ b/frontend/src/screens/DataDiagnostic.tsx @@ -32,7 +32,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - fetchRoutes: params => dispatch(fetchRoutes(params)), + fetchRoutes: () => dispatch(fetchRoutes), handleGraphParams: params => dispatch(handleGraphParams(params)), }); diff --git a/frontend/src/screens/Home.jsx b/frontend/src/screens/Home.tsx similarity index 100% rename from frontend/src/screens/Home.jsx rename to frontend/src/screens/Home.tsx diff --git a/frontend/src/screens/Isochrone.jsx b/frontend/src/screens/Isochrone.tsx similarity index 89% rename from frontend/src/screens/Isochrone.jsx rename to frontend/src/screens/Isochrone.tsx index 1a907bfc..0f62dd31 100644 --- a/frontend/src/screens/Isochrone.jsx +++ b/frontend/src/screens/Isochrone.tsx @@ -78,8 +78,29 @@ function getDirectionInfo(directionId, routeInfo) { return routeInfo.directions.find(dirInfo => dirInfo.id === directionId); } -class Isochrone extends React.Component { - constructor(props) { +interface Props { + [key: string]: any; +} + +interface State { + [key: string]: any; +} + +class Isochrone extends React.Component { + agency: any; + agencyId: any; + initialZoom: any; + initialCenter: any; + isochroneWorker: Worker; + layers: any[]; + isochroneLayers: any[]; + tripLayers: any[]; + routeLayers: any[]; + mapRef: React.RefObject; + container: any; + boundUpdate: any; + + constructor(props: Props) { super(props); // for now, only supports 1 agency at a time. @@ -272,13 +293,13 @@ class Isochrone extends React.Component { latlng = this.agency.defaultIsochroneCenter; } if (latlng) { - this.computeIsochrones(latlng, null); + this.computeIsochrones(latlng); } }, err => { const defaultLatLng = this.agency.defaultIsochroneCenter; if (defaultLatLng) { - this.computeIsochrones(this.agency.defaultIsochroneCenter, null); + this.computeIsochrones(this.agency.defaultIsochroneCenter); } }, ); @@ -289,7 +310,7 @@ class Isochrone extends React.Component { return; } this.resetMap(); - this.computeIsochrones(event.latlng, null); + this.computeIsochrones(event.latlng); } addReachableLocationsLayer(data) { @@ -326,7 +347,7 @@ class Isochrone extends React.Component { diffLayer.on('dblclick', e => { this.resetMap(); - this.computeIsochrones(e.latlng); + this.computeIsochrones(e.latlng, null); }); this.isochroneLayers.push({ tripMin, layer: diffLayer }); @@ -472,7 +493,7 @@ class Isochrone extends React.Component { } } - computeIsochrones(latLng, endLatLng) { + computeIsochrones(latLng, endLatLng = []) { if (!isInServiceArea(this.agencyId, latLng)) { return; } @@ -487,7 +508,7 @@ class Isochrone extends React.Component { const enabledRoutesArr = []; - this.props.routes.forEach(route => { + this.props?.routes?.forEach(route => { if (enabledRoutes[route.id] !== false) { enabledRoutesArr.push(route.id); } @@ -520,7 +541,7 @@ class Isochrone extends React.Component { // event arg removed if (newLatLng) { this.resetMap(); - this.computeIsochrones(newLatLng); + this.computeIsochrones(newLatLng, null); } }); this.layers.push(marker); @@ -647,7 +668,7 @@ class Isochrone extends React.Component { this.layers = []; this.isochroneLayers = []; - this.clearTripLayers(); + this.clearTripLayers(true); } clearTripLayers(clearTripInfo) { @@ -757,52 +778,54 @@ class Isochrone extends React.Component { opacity={0.6} /> {/* see http://maps.stamen.com for details */} - -
- - Date-Time Range -
- -
-
- -
-
-
+
+ +
- Max Trip Time - + Date-Time Range +
+ +
+
+ +
-
-
- - Routes - - - - - +
+ + Max Trip Time + + +
+
+ + Routes + + + + + + - - - {(routes || []).map(route => this.makeRouteToggle(route))} - + + {(routes || []).map(route => this.makeRouteToggle(route))} + +
-
- + +
{this.state.tripInfo ? (
{this.state.tripInfo}
@@ -854,7 +877,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - fetchRoutes: params => dispatch(fetchRoutes(params)), + fetchRoutes: () => dispatch(fetchRoutes), }); export default connect(mapStateToProps, mapDispatchToProps)(Isochrone); diff --git a/frontend/src/screens/NotFound.jsx b/frontend/src/screens/NotFound.tsx similarity index 100% rename from frontend/src/screens/NotFound.jsx rename to frontend/src/screens/NotFound.tsx diff --git a/frontend/src/screens/RouteScreen.jsx b/frontend/src/screens/RouteScreen.tsx similarity index 98% rename from frontend/src/screens/RouteScreen.jsx rename to frontend/src/screens/RouteScreen.tsx index a9b3cd29..98126a72 100644 --- a/frontend/src/screens/RouteScreen.jsx +++ b/frontend/src/screens/RouteScreen.tsx @@ -141,7 +141,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - fetchRoutes: params => dispatch(fetchRoutes(params)), + fetchRoutes: () => dispatch(fetchRoutes) }); export default connect(mapStateToProps, mapDispatchToProps)(RouteScreen); diff --git a/frontend/src/serviceWorker.js b/frontend/src/serviceWorker.ts old mode 100755 new mode 100644 similarity index 99% rename from frontend/src/serviceWorker.js rename to frontend/src/serviceWorker.ts index 17dabb44..12de7a6c --- a/frontend/src/serviceWorker.js +++ b/frontend/src/serviceWorker.ts @@ -1,3 +1,5 @@ +export default {} + // // This optional code is used to register a service worker. // // register() is not called by default. // diff --git a/frontend/src/store.js b/frontend/src/store.js index 81f9bbb0..619a1e03 100644 --- a/frontend/src/store.js +++ b/frontend/src/store.js @@ -1,11 +1,13 @@ +/* eslint-disable import/no-unresolved */ +/* eslint-disable import/extensions */ /* eslint-disable no-underscore-dangle */ import { createStore, applyMiddleware, combineReducers, compose } from 'redux'; import { connectRoutes } from 'redux-first-router'; import qs from 'qs'; import thunk from 'redux-thunk'; - import routesMap from './routesMap'; import * as reducers from './reducers'; + // import page from './reducers/page'; import * as actionCreators from './actions'; @@ -13,7 +15,7 @@ const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ actionCreators }) : compose; -export default function configureStore(preloadedState) { +export default function configureStore(preloadedState = {}) { const { reducer, middleware, enhancer } = connectRoutes(routesMap, { querySerializer: qs, }); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 00000000..14fc83c0 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "jsx": "react", + "outDir": "build", + "baseUrl": "src", + "allowJs": true, + "target": "es6", + "module": "commonjs", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "lib": ["esnext", "dom"], + "alwaysStrict": false, + "strictFunctionTypes": false, + "strictPropertyInitialization": false, + // temporary (need to fix) + "noImplicitAny": false, + "noImplicitThis": false, + "strictNullChecks": false + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "build"] +} \ No newline at end of file diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 15953c96..ee697e74 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -1,3 +1,19 @@ module.exports = { - resolve: {extensions: ['.js','.jsx']} -} \ No newline at end of file + entry: './src/index.ts', + output: { + filename: './dist/bundle.js', + }, + devtool: 'source-map', + resolve: { + extensions: ['', '.ts', '.tsx', '.js', '.jsx'], + }, + module: { + rules: [ + // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'. + { test: /\.tsx?$/, loader: 'awesome-typescript-loader' }, + + // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. + { test: /\.js$/, loader: 'source-map-loader' }, + ], + }, +}; diff --git a/package-lock.json b/package-lock.json index 958df32b..92623ebe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,45 @@ { "name": "opentransit", "version": "0.1.0", - "lockfileVersion": 1 + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.0.tgz", + "integrity": "sha512-WE4IOAC6r/yBZss1oQGM5zs2D7RuKR6Q+w+X2SouPofnWn+LbCqClRyhO3ZE7Ix8nmFgo/oVuuE01cJT2XB13A==" + }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" + }, + "@types/react": { + "version": "16.9.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.34.tgz", + "integrity": "sha512-8AJlYMOfPe1KGLKyHpflCg5z46n0b5DbRfqDksxBLBTUpB75ypDBAO9eCUcjNwE6LCUslwTz00yyG/X9gaVtow==", + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.9.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.6.tgz", + "integrity": "sha512-S6ihtlPMDotrlCJE9ST1fRmYrQNNwfgL61UB4I1W7M6kPulUKx9fXAleW5zpdIjUQ4fTaaog8uERezjsGUj9HQ==", + "requires": { + "@types/react": "*" + } + }, + "csstype": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz", + "integrity": "sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==" + }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" + } + } } diff --git a/package.json b/package.json index 4024014d..c878768d 100644 --- a/package.json +++ b/package.json @@ -12,5 +12,11 @@ "node": ">=8.14.0", "npm": ">=6.0.0", "yarn": "NO LONGER USED - Please use npm" + }, + "dependencies": { + "@types/node": "^13.13.0", + "@types/react": "^16.9.34", + "@types/react-dom": "^16.9.6", + "typescript": "^3.8.3" } } From e5b88e5eb111a9a09df1c63fe7bddcfcb44f51c4 Mon Sep 17 00:00:00 2001 From: akgupta89 Date: Sun, 19 Apr 2020 20:36:49 -0700 Subject: [PATCH 2/5] added eslint-typescript support --- frontend/.eslintrc.json | 34 ++++- frontend/package-lock.json | 136 ++++++++++++------ frontend/package.json | 7 +- frontend/src/App.tsx | 2 +- frontend/src/components/ControlPanel.tsx | 3 +- frontend/src/components/MapSpider.tsx | 11 +- frontend/src/components/MapStops.tsx | 1 + frontend/src/components/MareyChart.tsx | 12 +- frontend/src/components/ReactSelect.tsx | 18 ++- frontend/src/components/RouteTable.tsx | 13 +- .../src/components/WaitTimesHistogram.tsx | 5 +- frontend/src/react-app-env.d.ts | 2 +- frontend/src/reducers/page.ts | 2 +- frontend/src/screens/Isochrone.tsx | 28 ++-- frontend/src/screens/RouteScreen.tsx | 2 +- frontend/src/serviceWorker.ts | 2 +- package.json | 6 - 17 files changed, 193 insertions(+), 91 deletions(-) diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index c11fbca5..00fe646d 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -1,11 +1,17 @@ { - "extends": ["airbnb", "prettier", "prettier/react"], + "extends": [ + "airbnb", + "prettier", + "prettier/react", + "plugin:@typescript-eslint/recommended", + "plugin:import/typescript" + ], "plugins": ["react", "prettier"], "env": { "browser": true, "jest": true }, - "parser": "babel-eslint", + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 9, "sourceType": "module", @@ -40,14 +46,30 @@ "react/destructuring-assignment": "off", "react/jsx-filename-extension": [ 1, - { "extensions": [".js", ".jsx"] } + { "extensions": [".js", ".jsx", ".ts", ".tsx"] } ], - "react/prop-types": "off" + "react/prop-types": "off", + "import/extensions": [ + "error", + "ignorePackages", + { + "js": "never", + "jsx": "never", + "ts": "never", + "tsx": "never" + } + ], + //remove in future + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-explicit-any":"off" }, "settings": { "react": { "pragma": "React", - "version": "16.8.6" - } + "version": "detect" + }, + "import/extensions": [ + ".js", ".jsx", ".ts", ".tsx" + ] } } \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 547bfa58..17e6ffb1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -4552,49 +4552,49 @@ "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" }, "@typescript-eslint/eslint-plugin": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.25.0.tgz", - "integrity": "sha512-W2YyMtjmlrOjtXc+FtTelVs9OhuR6OlYc4XKIslJ8PUJOqgYYAPRJhAqkYRQo3G4sjvG8jSodsNycEn4W2gHUw==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.28.0.tgz", + "integrity": "sha512-w0Ugcq2iatloEabQP56BRWJowliXUP5Wv6f9fKzjJmDW81hOTBxRoJ4LoEOxRpz9gcY51Libytd2ba3yLmSOfg==", "requires": { - "@typescript-eslint/experimental-utils": "2.25.0", + "@typescript-eslint/experimental-utils": "2.28.0", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", "tsutils": "^3.17.1" }, "dependencies": { "regexpp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", - "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" } } }, "@typescript-eslint/experimental-utils": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.25.0.tgz", - "integrity": "sha512-0IZ4ZR5QkFYbaJk+8eJ2kYeA+1tzOE1sBjbwwtSV85oNWYUBep+EyhlZ7DLUCyhMUGuJpcCCFL0fDtYAP1zMZw==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz", + "integrity": "sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w==", "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.25.0", + "@typescript-eslint/typescript-estree": "2.28.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.25.0.tgz", - "integrity": "sha512-mccBLaBSpNVgp191CP5W+8U1crTyXsRziWliCqzj02kpxdjKMvFHGJbK33NroquH3zB/gZ8H511HEsJBa2fNEg==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.28.0.tgz", + "integrity": "sha512-RqPybRDquui9d+K86lL7iPqH6Dfp9461oyqvlXMNtap+PyqYbkY5dB7LawQjDzot99fqzvS0ZLZdfe+1Bt3Jgw==", "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.25.0", - "@typescript-eslint/typescript-estree": "2.25.0", + "@typescript-eslint/experimental-utils": "2.28.0", + "@typescript-eslint/typescript-estree": "2.28.0", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.25.0.tgz", - "integrity": "sha512-VUksmx5lDxSi6GfmwSK7SSoIKSw9anukWWNitQPqt58LuYrKalzsgeuignbqnB+rK/xxGlSsCy8lYnwFfB6YJg==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz", + "integrity": "sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q==", "requires": { "debug": "^4.1.1", "eslint-visitor-keys": "^1.1.0", @@ -6962,9 +6962,9 @@ } }, "core-js-pure": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz", - "integrity": "sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==" + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==" }, "core-util-is": { "version": "1.0.2", @@ -8777,17 +8777,6 @@ "has": "^1.0.3" } }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "object.values": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", @@ -8800,9 +8789,9 @@ } }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz", + "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==", "requires": { "path-parse": "^1.0.6" } @@ -8811,14 +8800,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "xregexp": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", - "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", - "requires": { - "@babel/runtime-corejs3": "^7.8.3" - } } } }, @@ -13569,6 +13550,65 @@ "has": "^1.0.3" } }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "requires": { + "has": "^1.0.3" + } + } + } + }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -20876,6 +20916,14 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "xregexp": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", + "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", + "requires": { + "@babel/runtime-corejs3": "^7.8.3" + } + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 7bb4cdd6..72a4dd52 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -37,6 +37,11 @@ }, "devDependencies": { "@types/moment-timezone": "^0.5.13", + "@types/node": "^13.13.0", + "@types/react": "^16.9.34", + "@types/react-dom": "^16.9.6", + "@typescript-eslint/eslint-plugin": "^2.28.0", + "@typescript-eslint/parser": "^2.28.0", "babel-eslint": "10.1.0", "eslint": "^6.8.0", "eslint-config-airbnb": "^17.1.1", @@ -72,7 +77,7 @@ } }, "lint-staged": { - "src/**/*.{js,jsx}": [ + "src/**/*.{js,jsx,ts,tsx}": [ "prettier --write", "eslint --fix src/", "git add" diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 2f3f4a63..2d2929b7 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -41,7 +41,7 @@ const theme = createMuiTheme({ sm: 600, md: 1050, lg: 1280, - xl: 1920 + xl: 1920, }, }, palette: { diff --git a/frontend/src/components/ControlPanel.tsx b/frontend/src/components/ControlPanel.tsx index 04ffd6e8..78739743 100644 --- a/frontend/src/components/ControlPanel.tsx +++ b/frontend/src/components/ControlPanel.tsx @@ -112,7 +112,8 @@ function ControlPanel(props) { const hoverStop = selectedRoute ? selectedRoute.stops[stopId] : null; - mapNode.setAttribute("style", + mapNode.setAttribute( + 'style', `--stop-name: "${hoverStop ? hoverStop.title : ''}"`, ); } diff --git a/frontend/src/components/MapSpider.tsx b/frontend/src/components/MapSpider.tsx index 05240fab..96b9677d 100644 --- a/frontend/src/components/MapSpider.tsx +++ b/frontend/src/components/MapSpider.tsx @@ -49,11 +49,12 @@ interface State { class MapSpider extends Component { agency: any; + routeLayers: any[]; + mapRef: any; + boundUpdate: any; - onMouseOver: Function = (e: any) => {}; - onMouseOut: Function = (e: any) => {}; constructor(props: Props) { super(props); @@ -286,14 +287,16 @@ class MapSpider extends Component { return true; }} onFocus={e => { - this.onMouseOver(e); + e.target.setStyle({ opacity: 1, weight: computedWeight + 4 }); + return true; }} onMouseOut={e => { e.target.setStyle({ opacity: 0.5, weight: computedWeight }); return true; }} onBlur={e => { - this.onMouseOut(e); + e.target.setStyle({ opacity: 0.5, weight: computedWeight }); + return true; }} // when this route segment is clicked, plot only the stops for this route/dir by setting the first stop onClick={e => { diff --git a/frontend/src/components/MapStops.tsx b/frontend/src/components/MapStops.tsx index dc5775fa..cd6a3066 100644 --- a/frontend/src/components/MapStops.tsx +++ b/frontend/src/components/MapStops.tsx @@ -23,6 +23,7 @@ interface State { class MapStops extends Component { agency: any; + boundUpdate: any; constructor(props: Props) { diff --git a/frontend/src/components/MareyChart.tsx b/frontend/src/components/MareyChart.tsx index 6de8b850..0619428a 100644 --- a/frontend/src/components/MareyChart.tsx +++ b/frontend/src/components/MareyChart.tsx @@ -17,7 +17,7 @@ import { import '../../node_modules/react-vis/dist/style.css'; import { connect } from 'react-redux'; import { Radio, FormControl, FormControlLabel } from '@material-ui/core'; -import Moment from 'moment' +import Moment from 'moment'; // eslint-disable-next-line import MomentTZ from 'moment-timezone/builds/moment-timezone-with-data-10-year-range'; // this augments Moment import * as d3 from 'd3'; @@ -66,7 +66,9 @@ const MareyChart: React.FC = (props: Props) => { const [hintValue, setHintValue] = useState(); const [tripHighlight, setTripHighlight] = useState(); const [processedArrivals, setProcessedArrivals] = useState(); // where the tripData gets stored - const [selectedOption, setSelectedOption] = useState(INBOUND_AND_OUTBOUND); + const [selectedOption, setSelectedOption] = useState( + INBOUND_AND_OUTBOUND, + ); const agency = getAgency(graphParams.agencyId); const timezoneId = agency ? agency.timezoneId : 'UTC'; @@ -199,7 +201,9 @@ const MareyChart: React.FC = (props: Props) => { const stops = myArrivals.stops; const startTime = myArrivals.start_time; - const startHourOfDay = Moment.unix(startTime).utcOffset(timezoneId).hour(); + const startHourOfDay = Moment.unix(startTime) + .utcOffset(timezoneId) + .hour(); const routeId = myArrivals.route_id; const route = myRoutes.find(myRoute => myRoute.id === routeId); @@ -473,7 +477,7 @@ const MareyChart: React.FC = (props: Props) => { ) : ( {arrivalsErr || 'Loading...'} ); -} +}; const mapStateToProps = state => ({ routes: state.routes.data, diff --git a/frontend/src/components/ReactSelect.tsx b/frontend/src/components/ReactSelect.tsx index 7594e7bd..f9e505f1 100644 --- a/frontend/src/components/ReactSelect.tsx +++ b/frontend/src/components/ReactSelect.tsx @@ -94,13 +94,17 @@ function Control(props) { ref={textRef} fullWidth InputProps={{ - inputComponent: () =>
+ inputComponent: () => ( +
+ {{ children }} +
+ ), }} label={textFieldProps.label} InputLabelProps={inputLabelProps} diff --git a/frontend/src/components/RouteTable.tsx b/frontend/src/components/RouteTable.tsx index 8bee0eb0..80dc617d 100644 --- a/frontend/src/components/RouteTable.tsx +++ b/frontend/src/components/RouteTable.tsx @@ -1,7 +1,16 @@ import React, { useState, Fragment } from 'react'; import PropTypes from 'prop-types'; import { lighten, makeStyles, useTheme } from '@material-ui/core/styles'; -import { Popover, Table, TableBody, TableCell, TableHead, TableRow, TableSortLabel, IconButton } from '@material-ui/core'; +import { + Popover, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + TableSortLabel, + IconButton, +} from '@material-ui/core'; import InfoIcon from '@material-ui/icons/InfoOutlined'; import { connect } from 'react-redux'; import Navlink from 'redux-first-router-link'; @@ -102,7 +111,7 @@ const EnhancedTableHead: React.FC = (props: Props) => { ); -} +}; EnhancedTableHead.propTypes = { onRequestSort: PropTypes.func.isRequired, diff --git a/frontend/src/components/WaitTimesHistogram.tsx b/frontend/src/components/WaitTimesHistogram.tsx index 1f169fa6..0ff08c14 100644 --- a/frontend/src/components/WaitTimesHistogram.tsx +++ b/frontend/src/components/WaitTimesHistogram.tsx @@ -65,7 +65,10 @@ function WaitTimesHistogram(props) { { title: 'Scheduled', color: CHART_COLORS[0], - data: getHistogramChartData(scheduledWaitTimes.histogram, null), + data: getHistogramChartData( + scheduledWaitTimes.histogram, + null, + ), stroke: '#333', cluster: 'second', opacity: 0.25, diff --git a/frontend/src/react-app-env.d.ts b/frontend/src/react-app-env.d.ts index 6431bc5f..30da8962 100644 --- a/frontend/src/react-app-env.d.ts +++ b/frontend/src/react-app-env.d.ts @@ -1 +1 @@ -/// +// / diff --git a/frontend/src/reducers/page.ts b/frontend/src/reducers/page.ts index c1882a11..ea120e08 100644 --- a/frontend/src/reducers/page.ts +++ b/frontend/src/reducers/page.ts @@ -26,5 +26,5 @@ export function typeForPage(page) { return currentType; } -export default (state = 'DASHBOARD', action: {type: string}) => +export default (state = 'DASHBOARD', action: { type: string }) => components[action.type] || state; diff --git a/frontend/src/screens/Isochrone.tsx b/frontend/src/screens/Isochrone.tsx index 0f62dd31..661ad3ed 100644 --- a/frontend/src/screens/Isochrone.tsx +++ b/frontend/src/screens/Isochrone.tsx @@ -88,16 +88,27 @@ interface State { class Isochrone extends React.Component { agency: any; + agencyId: any; + initialZoom: any; + initialCenter: any; + isochroneWorker: Worker; + layers: any[]; + isochroneLayers: any[]; + tripLayers: any[]; + routeLayers: any[]; + mapRef: React.RefObject; + container: any; + boundUpdate: any; constructor(props: Props) { @@ -503,16 +514,10 @@ class Isochrone extends React.Component { const endTimeStr = this.props.endTime; const timeStr = startTimeStr && endTimeStr ? `${startTimeStr}-${endTimeStr}` : ''; - const { maxTripMin, enabledRoutes } = this.state; - - const enabledRoutesArr = []; - - this.props?.routes?.forEach(route => { - if (enabledRoutes[route.id] !== false) { - enabledRoutesArr.push(route.id); - } - }); + const enabledRoutesArr = this.props.routes + .filter(route => enabledRoutes[route.id] !== false) + .map(route => route.id); const computeId = [ latLng.lat, @@ -811,7 +816,10 @@ class Isochrone extends React.Component { - - - + +
+ + Max Trip Time + + +
+
+ + Routes + + + + + - - {(routes || []).map(route => this.makeRouteToggle(route))} - -
+
+ + {(routes || []).map(route => this.makeRouteToggle(route))} +
-
-
+
+ {this.state.tripInfo ? (
{this.state.tripInfo}
@@ -886,7 +882,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - fetchRoutes: () => dispatch(fetchRoutes), + fetchRoutes: params => dispatch(fetchRoutes(params)), }); export default connect(mapStateToProps, mapDispatchToProps)(Isochrone); diff --git a/frontend/src/screens/RouteScreen.tsx b/frontend/src/screens/RouteScreen.tsx index 4f60fb46..8408e8fd 100644 --- a/frontend/src/screens/RouteScreen.tsx +++ b/frontend/src/screens/RouteScreen.tsx @@ -142,7 +142,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - fetchRoutes: () => dispatch(fetchRoutes), + fetchRoutes: params => dispatch(fetchRoutes(params)), }); export default connect(mapStateToProps, mapDispatchToProps)(RouteScreen); diff --git a/frontend/src/store.js b/frontend/src/store.ts similarity index 84% rename from frontend/src/store.js rename to frontend/src/store.ts index 619a1e03..45216c58 100644 --- a/frontend/src/store.js +++ b/frontend/src/store.ts @@ -7,12 +7,11 @@ import qs from 'qs'; import thunk from 'redux-thunk'; import routesMap from './routesMap'; import * as reducers from './reducers'; - // import page from './reducers/page'; import * as actionCreators from './actions'; -const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ - ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ actionCreators }) +const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ + ? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ actionCreators }) : compose; export default function configureStore(preloadedState = {}) { @@ -20,10 +19,10 @@ export default function configureStore(preloadedState = {}) { querySerializer: qs, }); + // @ts-ignore const rootReducer = combineReducers({ ...reducers, location: reducer }); const middlewares = applyMiddleware(thunk, middleware); const enhancers = composeEnhancers(enhancer, middlewares); - const store = createStore(rootReducer, preloadedState, enhancers); return { store }; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 743cc33c..e110724c 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -23,6 +23,7 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, + // remove in the future "noImplicitAny": false, "noImplicitThis": false, "strictNullChecks": false, From 5c07fd344ef1b5edbd54a8fa26d374296f1b080b Mon Sep 17 00:00:00 2001 From: akgupta89 Date: Mon, 20 Apr 2020 19:46:18 -0700 Subject: [PATCH 5/5] added typescript references to readme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c82d47fc..660378de 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Our pull request template will request that you fill out some key fields. It'll ### Code style -This repository uses eslint to enforce a consistent style for frontend JavaScript code. +This repository uses eslint to enforce a consistent style for frontend Typescript code. Before committing, run `dev/docker-lint.sh` (Mac/Linux) or `dev\docker-lint.bat` (Windows) to check for style errors and automatically fix formatting issues. (You will need to run `docker-compose up` or `docker-compose build` at least once before the docker-lint script will work.) @@ -113,6 +113,7 @@ The build steps are defined in `cloudbuild.yaml`. package managers offer similar performance, we were already using NPM for backend package management, and the Yarn roadmap did not offer compelling improvements going forward. +- **Typescript** - To enforce build time static typing and make our code more scalable. - **React** - Selected for popularity, simple view, and speedy virutal DOM. Code lives in the `/frontend` directory. It was built using [Create React App](https://facebook.github.io/create-react-app/docs/folder-structure). - **Material UI** - which we use over Bootstrap since MUI doesn't rely on jQuery. It has a @@ -122,7 +123,7 @@ popular React framework and looks great on mobile. - **React Hooks** - to manage interactions with state management. - **Functional Components** - We migrated away from ES6 React Components and toward React [Functional Components](https://reactjs.org/docs/components-and-props.html) due to the simpler component logic and the ability to use React Hooks that Functional Components offer. -- **ESLint** - Linting set in the format of AirBNB Style. +- **ESLint** - Linting set in the format of AirBNB Style + with Typescript additions. - **Prettier** - Code formatter to maintain standard code format for the frontend code. - **Husky** - Pre-commit hook to trigger Prettier auto formatting before pushing to Github.