Skip to content
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

SAFB-249: Group Icon Functionality #305

Open
wants to merge 8 commits into
base: development
Choose a base branch
from

Conversation

RoryMacGregor88
Copy link
Contributor

@RoryMacGregor88 RoryMacGregor88 commented Sep 29, 2022

Closes #SAFB-249

This allows group icons to be interacted with the same way as cluster icons and individual icons.

Fixed the pin functionality for the group icons, which turned out to be a pretty tricky change.

It involved updating the base-level PinLayer to recognise the difference between a cluster and a group,
then call the passed getPinColor method in that case.

Then the function in mapHelpers that determines pin color had to be updated to also recognise groups,
and work out if the selected item is in that group by analyising the coordinates of each.

Finally, each of the Chatbot screens had to be updated to find the selected item from the list
of all, then pass the id and coordinates to the layer handler in order to make all of the above possible.
Added the fix to allow group icons to update to the in-situ cameras panel. There were some
strange bugs here that greatly slowed down developent, one of which was there being a second
GeoJsonPinLayer in the alertList for some reason, that was resetting the icons as soon one
was clicked. And the other was the cameraList being initialised to an array, even though the
returned data is a featureCollection object.
Reverted removing the duplicated GeoJsonPinLayer in in-situ, as it doesn't need to convert to
GeoJson like the helper one does. However, I had to extend the dupliated one to 1. include the pinInfo
required to identify the selected icon, and 2. pass this function through to the list so that both the
list and map are sharing the same GeoJsonLayer.
After some refactoring, the clicks for in-situ cameras (which work a bit differently from the others)
are working as expected. This involved a bit of juggling between when to use alert ids and camera ids,
but the camera ids seem to be the correct choice for this kind of identification.

Also refactored the PinLayer to be able to differentiate between clusters and groups in the getIconColor function,
and the generic mapHelper to be able to tell if incoming data is already a feature collection before reshaping.
Refactores the click handler for in-situ to make it cleaner, and fixed the events group click
as it was not working correctly.
Reverted the condition added to the PinLayer, as it turns out
it is unnecessary.

IssueID: SAFB-249
By searching for the selected icon inside an array of cluster leaf node ids, it allows for pinpoint
accurate selection, as opposed to the coordinate match method used before, which worked (kind of),
but was not nearly as accurate. Is also much simpler code to read.
Just moved a color from being hardcoded in place to using a constant.
@allynt
Copy link
Contributor

allynt commented Oct 11, 2022

Hmm... I've just noticed that not all the clustered pins have the correct circle:

image

Copy link

@marksmall marksmall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few changes requested, nothing that major though.

properties,
geometry,
};
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen this self same code in stuff @stevefaeembra has worked on, enough times that maybe it should be a utility function. Just a suggestion, for now.

@@ -70,7 +70,14 @@ const Comms = () => {

useEffect(() => {
if (allReports.length > 0) {
setIconLayer(getIconLayer(allReports, MAP_TYPES.COMMUNICATIONS, 'communications', dispatch, setViewState, {id: commID}));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line as the first bit of the if isn't great, in my opinion, but it is just my opinion, I know some devs like it and others seem to accidentally do it.

@@ -84,7 +84,14 @@ const Missions = () => {

useEffect(() => {
if (allMissions.length > 0) {
setIconLayer(getIconLayer(allMissions, MAP_TYPES.MISSIONS, 'target', dispatch, setViewState, {id: missionId}));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same again

? { center: selectedMission.location, id: missionId }
: {}

setIconLayer(getIconLayer(allMissions, MAP_TYPES.MISSIONS, 'target', dispatch, setViewState, pinInfo));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code in these 2 useEffects are almost identical, find an item by it's id in an array, then create an object from it and other info, then create an icon layer. I get that the arrays are differnt and the Map_TYPES etc, but the idea is the same, that is ripe for a utility function. Repeating it twice isn't a big deal, but what if you had to do it 10 times, for instance.

@@ -78,7 +78,14 @@ const People = () => {

useEffect(() => {
if (allPeople.length > 0) {
setIconLayer(getIconLayer(allPeople, MAP_TYPES.PEOPLE, 'people', dispatch, setViewState, {id: peopleId}));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and again, leading empty line.

? { center: selectedPeople.location, id: peopleId }
: {};

setIconLayer(getIconLayer(allPeople, MAP_TYPES.PEOPLE, 'people', dispatch, setViewState, pinInfo));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about a utility function here as I made before.

? { center: selectedReport.location, id: reportId }
: {};

setIconLayer(getIconLayer(reshapedReports, MAP_TYPES.REPORTS, 'report', dispatch, setViewState, pinInfo, 'report_id'));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and again

@@ -77,7 +77,7 @@ const Alert = ({ card, alertId, setSelectedAlert, setFavorite, t }) => {
return (
<>
<Card
onClick={() => setSelectedAlert(card.id)}
onClick={() => setSelectedAlert(card.id, card.camera_id)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a judgement call really, passing in potentially many params, rather than grouping them and passing a single object and leaving it up to the setSelectedAlert function to figure out what it needs from the card object. Say in future, you had to add another parameter, you keep changing the interface of the function, so other uses might need to pass in null|undefined, whereas if it just took an object, the interface doesn't change, but as I say, at this point, it is a judgement call

setCameraId(cameraId)
}
}

return (
<>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not your code I get it, but is this fragment <></> needed, does the Row not suffice?

: {};

setIconLayer(getIconLayer(cameraList.features, MAP_TYPES.IN_SITU, 'camera', dispatch, setViewState, pinInfo));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as before about the utility function. That is 4 occurrences of the same idea, just using different params.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants