-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
render route on map on table row hover #537
base: master
Are you sure you want to change the base?
Conversation
Thanks for doing this. This seems like a good enhancement overall, and it is very responsive (which I know can be a challenge with react-leaflet). I haven't used React.memo before but this seems like a natural place to use it. I wanted to start with some high level feedback before getting into a detailed review. On the technical side, I was wondering if we can avoid the use of setTimeout/clearTimeout. These kinds of global function calls are difficult to understand and debug. Also, pushing state from Dashboard down to its children is a bit of an antipattern that Redux was meant to solve. Can you use Redux state to communicate between components and avoid the use of setTimeout? The spider selection state is done using Redux, you should be able to add stuff alongside that. On the UI design side, everything a matter of subjective opinion but my two cents: I'd like the see the hover effect done a little differently. On MapStops, we use a wider white polyline to provide some contrast against the map, and then a wider indigo polyline between the selected stops. So can we do the hover effect using a white or indigo outline? I'd also prefer the shield sizes and colored line widths to stay as they were. The width conveys the frequency of the line, so that information gets lost when the width is scaled up, especially if there is no spider selection. I'm hoping the white or indigo outline lets you keep the opacities for the colored polylines where there were originally, and no changes to the shields. It seems natural that the hover effect should go both ways, so when you highlight a route segment, the route's row in the table is also highlighted (the light gray background in the table row, which might be a css effect). |
Thanks for the detailed feedback. My rationale behind the route only showing directions within range of the marker was that having a marker down already eliminated whole routes from the table making them unselectable, so the user would equate what is shown on the map to what remains on the table and vice versa. On the other hand clicking the route involves choosing either direction so if you still think it would be more natural to always show both directions then I don't disagree. Regarding the timeout, removing it won't have a huge impact but it will be noticeable when moving through the routes consecutively at a somewhat fast rate. |
I'm not sure what part of my feedback you're referring to here? It looks the visibility of routes when a selection is made hasn't changed in this PR, and that is good. Aside from stylistic changes to how the route highlights are done, I was suggesting that when the user mouses over the map (triggering the tooltip), we also highlight the route's row in the table.
For this particular feature, I think that is fine. Let's try it out. |
My mistake, after I read the paragraph again it seems I misunderstood. Removed timeout on heroku demo. |
Hey Raymond, We were all going crazy about your feature at the meeting just now. In the words of one of our members, it's "tight." Couple pieces of feedback: Terence was saying that the highlighting is very subtle now, making it hard to pick out the route. (Before it was a bit too much?) Perhaps something in between would be better. In the "live" version of OpenTransit, each line is a different width based on how often the bus comes. I don't see that in this version of yours. Can you put back that feature? |
Also a good suggestion from Terence. How hard would that be to add? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See feedback. Almost there!
Only change that's a "must" is putting the variable line widths back. Other things can be put in separate issues so we can address them later. |
I did already undo the changes to the scale, it just seems that the route stats didn't update beyond a point as you can see there are no scores on the route table. I didn't look into it as I had assumed it was from a conflict on the backend. If you go back to Feb 9 or earlier you will see there are stats and the lines reflect them. As for highlighting the row it sounds possible. |
The code looks pretty good, but I can't test it effectively. I think there's some problems with the latest GTFS feed for Muni, from looking at some of the newest PRs, so we have duplicate routes. When I click a point on the map, I still see most or all routes in the table, where I'm expecting to see just the routes that are visible on the map. I don't see a code change in this PR that would cause that, or maybe I missed it. It might be helpful to address the git conflicts, as this should simplify the diffs a bit. A lot of changes are due to the linter/prettier fixing things, which are now also fixed on master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good, I like the new styling for the highlighted route on the map. Also, don't know if you agree, but I like the code better with redux actions vs setTimeout. Seems like a nicer way to have components talk to each other that won't break if the component hierarchy gets rearranged.
I just had a few questions about some bits of the code, mostly from an ease of maintenance standpoint.
}; | ||
|
||
/** | ||
* Get additional scale when near max zoom to account for increased periphery |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand this comment, what is "increased periphery"? Also, I tried having this function always return 0 vs its current behavior at various zoom levels below and above 17. I couldn't actually see a difference, what is the issue this code solves? This method seems kind of hard to understand and maintain if we want to adjust how the map renders later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's really subtle. May just be me being nitpicky after staring at it for so long. Basically I find that when I'm zoomed out I'm looking near the marker so it's easy to spot when the route gets outlined but when I'm zoomed in to a hot spot with many routes on screen it's harder to notice, particularly when the route is less traveled and near the edge of the map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, okay. I guess some change is needed here, either add the above text as a comment so others will better understand why this function is needed, or remove the function to keep things more maintainable and easier to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this without the additional scale function? I’m fine with this, I’d rather not have additional logic for zoom levels greater than 17.
frontend/src/actions/index.js
Outdated
|
||
export function handleSegmentHover(segmentRouteId) { | ||
return function(dispatch) { | ||
dispatch({ type: 'RECEIVED_SEGMENT_HOVER', segmentRouteId }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name "segment" threw me off for a bit, until I realized this was just the id of the route being hovered in the map. Can we change it to something like "spider hover", "map hover", or "spider map hover"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think the term "segment" is going to take on a more specialized meaning now (as "the route between two adjacent stops"). Let's not use that term for other things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given Neel's description segment seems increasingly appropriate to me since "the route between two adjacent stops" is precisely what is being hovered. If anything shouldn't just the parameter be changed to routeId since the routeId is not specific to each segment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or we could throw all of that into a blender and have handleSpiderSegmentHover. I guess it really just depends how specific you want it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that segmentRouteId should just be routeId. Going by memory, I don’t remember the term “segment” being used in the front end code, so “handleSegmentHover” doesn’t mean much to me. handleSpiderSegmentHover is a lot better and is acceptable to me, but I’d prefer handleSpiderHover more.
<this.MemoizedDownstreamLines | ||
latLng={spiderSelection.latLng} | ||
stops={spiderSelection.stops} | ||
statsByRouteId={statsByRouteId} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I understand of the React.memo docs, the idea is that the memoized component skips re-rendering if a shallow compare of the props matches the props used for rendering? So the props you're passing in are the ones that, if different, force rerendering of downstream lines? Can you add some comments to that effect? It's not intuitive at first, since DownstreamLines doesn't consume all these props directly.
|
||
useEffect(() => { | ||
return () => onRowHover(null); | ||
}, [onRowHover]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this useEffect? Looks like it only runs on first render? I tried commenting out and didn't see any difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe when I navigated to a different page while still having the route hovered (via back or forward on mouse) and then returning to the page the route is still hovered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, was able to reproduce that. Can you add some comments to that effect? useEffect is a bit of swiss army knife, meaning it's hard to know what the effect is being used for. My interpretation is that this effect runs on mount and unmount to reset the table hover state.
@@ -414,14 +426,21 @@ function RouteTable(props) { | |||
rowCount={displayedRouteStats.length} | |||
columns={columns} | |||
/> | |||
<TableBody> | |||
<TableBody onMouseLeave={() => onRowHover(null)}> | |||
{stableSort(displayedRouteStats, order, orderBy).map(row => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is sort of unrelated to your PR. We have this duplicate route id thing going on right now on the back end, and I noticed that it generates a bunch of console warnings due to duplicate TableRow keys. Also this breaks the spider map's filtering of the table rows. I noticed that filtering works again if we use unique keys -- so instead of keying on route id, we could just key on row index, like "routerow" + index.
{stableSort(displayedRouteStats, order, orderBy).map(row => { | |
{stableSort(displayedRouteStats, order, orderBy).map((row, index) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So are we just going to chuck it in here so we wont need a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the duplicate problem is fixed now, so I guess it’s not needed. It was mainly just to get the spider filtering working again to make testing this PR easier.
Fixes #389
Proposed changes
Render route on map when hovering over route table. When no spider exists both directions are rendered. When spider exists only render directions already on the spider.
Currently on hover, the starting stop (closest stop to spider marker) of the route and stops are fully opaque whilst polylines are slightly less transparent (only when spider exists), and of course everything is slightly larger. I find that when the polylines are too transparent you sometimes see a mess of colors underneath making it harder to see but when it's too solid you can't see the stops. Thoughts?
Also the map shields of other routes currently stay on top of the hovered route (except the shield). Is this preferable?
Link to demo, if any
https://open-transit-hover-line.herokuapp.com/