@@ -492,7 +604,14 @@ class MapSpider extends Component {
opacity={0.3}
/>
{/* see http://maps.stamen.com for details */}
-
+
+
+ {/* Props are shallow compared with previous props and skips re-rendering if they are equal */}
+
{startMarkers}
@@ -542,6 +661,7 @@ const mapDispatchToProps = dispatch => {
return {
onSpiderMapClick: (stops, latLng) =>
dispatch(handleSpiderMapClick(stops, latLng)),
+ onSpiderHover: routeId => dispatch(handleSpiderHover(routeId)),
dispatch,
};
};
diff --git a/frontend/src/components/RouteTable.jsx b/frontend/src/components/RouteTable.jsx
index f222c1da..a04ba16f 100644
--- a/frontend/src/components/RouteTable.jsx
+++ b/frontend/src/components/RouteTable.jsx
@@ -1,4 +1,4 @@
-import React, { useState, Fragment } from 'react';
+import React, { useState, Fragment, useEffect } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { lighten, makeStyles, useTheme } from '@material-ui/core/styles';
@@ -24,6 +24,7 @@ import {
scoreBackgroundColor,
scoreContrastColor,
} from '../helpers/routeCalculations';
+import { handleTableRowHover } from '../actions';
function getComparisonFunction(order, orderBy) {
// Sort null values to bottom regardless of ascending/descending
@@ -228,6 +229,9 @@ const useStyles = makeStyles(theme => ({
width: '100%',
marginTop: theme.spacing(3),
},
+ artificialHover: {
+ backgroundColor: 'rgba(0, 0, 0, 0.07)',
+ },
tableWrapper: {
overflowX: 'auto',
},
@@ -252,7 +256,12 @@ function RouteTable(props) {
const dense = true;
const theme = useTheme();
- const { statsByRouteId } = props;
+ const { statsByRouteId, onTableRowHover, spiderSelection } = props;
+
+ // Null hovered route on mount and unmount to prevent route being already highlighted when entering Dashboard
+ useEffect(() => {
+ return () => onTableRowHover(null);
+ }, [onTableRowHover]);
function handleRequestSort(event, property) {
const isDesc = orderBy === property && order === 'desc';
@@ -414,14 +423,21 @@ function RouteTable(props) {
rowCount={displayedRouteStats.length}
columns={columns}
/>
-
+ onTableRowHover(null)}>
{stableSort(displayedRouteStats, order, orderBy).map(row => {
+ let hover;
+ if (row.route.id === spiderSelection.routeId) {
+ hover = classes.artificialHover;
+ }
+
return (
onTableRowHover(row.route)}
+ classes={{ root: hover }}
>
{columns.map(column => {
return (
@@ -454,4 +470,11 @@ const mapStateToProps = state => ({
query: state.location.query,
});
-export default connect(mapStateToProps)(RouteTable);
+const mapDispatchToProps = dispatch => ({
+ onTableRowHover: route => dispatch(handleTableRowHover(route)),
+});
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(RouteTable);
diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.js
index 381d7b8f..3b3dcd57 100644
--- a/frontend/src/reducers/index.js
+++ b/frontend/src/reducers/index.js
@@ -121,6 +121,8 @@ export function arrivals(state = initialArrivals, action) {
const initialSpiderSelection = {
stops: [],
latLng: null,
+ tableHoverRoute: null,
+ routeId: null,
};
export function spiderSelection(state = initialSpiderSelection, action) {
@@ -131,6 +133,16 @@ export function spiderSelection(state = initialSpiderSelection, action) {
stops: action.stops,
latLng: action.latLng,
};
+ case 'RECEIVED_TABLE_ROW_HOVER':
+ return {
+ ...state,
+ tableHoverRoute: action.tableHoverRoute,
+ };
+ case 'RECEIVED_SPIDER_HOVER':
+ return {
+ ...state,
+ routeId: action.routeId,
+ };
default:
return state;
}