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

Save shape updates #141

Merged
merged 8 commits into from
Oct 20, 2022
Merged

Save shape updates #141

merged 8 commits into from
Oct 20, 2022

Conversation

mstone121
Copy link
Contributor

@mstone121 mstone121 commented Oct 18, 2022

Overview

This PR adds functionality that saves a boundary when it is updated.

Updating is debouced with a three second interval. Each update is patched immediately and directly into the RTK query cache. After the three second interval, the latest update is sent to the server. If the server fails, changes are rolled back to the last saved state.

Closes #130

Notes

The map is re-rendering on update. I believe this is because a component above the map is using the boundary details query. When the shape is updated, this query is updated, which triggers a re-render. This should be addressed here if possible or in a later card.

Testing Instructions

Checklist

  • fixup! commits have been squashed
  • CHANGELOG.md updated with summary of features or fixes, following Keep a Changelog guidelines
  • README.md updated if necessary to reflect the changes
  • CI passes after rebase

Copy link
Contributor

@rajadain rajadain left a comment

Choose a reason for hiding this comment

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

This is generally looking good!

Let's take away the Validator's ability to change the shape.

Also, it would be nice to fix the map flashing. Would recommend that be given a shot in this PR, and only deferred if too complex.

src/django/api/views/boundary.py Outdated Show resolved Hide resolved
if not ShapeSerializer.coordinates_are_closed(coordinates):
coordinates = ShapeSerializer.get_closed_coordinates(coordinates)

return Polygon(*coordinates)
Copy link
Contributor

Choose a reason for hiding this comment

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

This may be opposed to / need to be overridden when #127 is implemented.

class BadRequestException(APIException):
status_code = 400
default_detail = 'There was a problem with your request.'
default_code = 'bad_request'
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice job adding clear exceptions

src/django/api/views/boundary.py Outdated Show resolved Hide resolved
@@ -45,6 +76,18 @@ export default function DrawTools({ details }) {
);
}

function getDrawMode({ status, userRole }) {
if (userRole === ROLES.VALIDATOR && status === BOUNDARY_STATUS.IN_REVIEW) {
Copy link
Contributor Author

@mstone121 mstone121 Oct 19, 2022

Choose a reason for hiding this comment

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

This used to be:

        [BOUNDARY_STATUS.SUBMITTED, BOUNDARY_STATUS.IN_REVIEW].includes(
            details.status
        ) &&
        user.role === ROLES.VALIDATOR

I'm thinking that the distinction between IN_REVIEW and SUBMITTED is the presence of a row in the Reviews database table. If a Validator clicks "Review" on a boudary, an entry should be added to the Reviews table before taking them to the /draw page.

Otherwise the Review creation logic would happen the first time a review is saved. This feels more complicated to me, however, it's something that could be handled entirely by the back-end.

Copy link
Contributor

Choose a reason for hiding this comment

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

This understanding is correct.

DRAFT = Row in Submission table, with submitted_at = NULL
SUBMITTED = That row has a value for submitted_at
IN_REVIEW = Row in Review table, with reviewed_at = NULL
NEEDS REVISIONS = That row has a value for reviewed_at
APPROVED = Row in Approval table, with a value for approved_at

I'm not sure how much we'll end up using IN_REVIEW in practice.

return (
<Flex>
<Sidebar />
<Box flex={1} position='relative'>
<Map>
<Layers mode={mode} />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is Layers going to need access to mode? If so, maybe boundary details should be loaded in a separate component above DrawTools and Layers, but below Map.

Copy link
Contributor

@rajadain rajadain Oct 19, 2022

Choose a reason for hiding this comment

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

maybe boundary details should be loaded in a separate component above DrawTools and Layers, but below Map.

I like that arrangement.

Alternatively, if Layers uses the same RTKQuery hook to get the boundary details, will it not get a cached value? i.e. it should be fetched only once for the different components that request it, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alternatively, if Layers uses the same RTKQuery hook to get the boundary details, will it not get a cached value? i.e. it should be fetched only once for the different components that request it, right?

Yep, but then we would also need to handle the various states of the request (isFetching, error, success) in that component as well. I like to have one parent component handling all this and passing the non-null data to the children.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point.

Copy link
Contributor

@rajadain rajadain left a comment

Choose a reason for hiding this comment

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

Playing with this a bit, I think the reverting on fail to save is too harsh. For rural areas that may have flaky internet, a slight drop in connectivity can make the user lose their work:

2022-10-19.15.33.33.mp4

Failures here should be silent, and the shape on the map should remain unchanged.

When the contributor clicks "Save and back" or "Review and submit", we should also send the shape then. If there are internet connectivity issues then, we should let the user know, and stop them from navigating away from this page and losing their work. All this should be done as part of #132.

For this card, making the save failures silent in the background is enough.

Does that make sense?

boundary.latest_submission.shape = serializer.validated_data
boundary.latest_submission.save()

return Response()
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider returning an HTTP 204 NO CONTENT here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -19,7 +19,7 @@ const DRAW_MODES = {

export default function Draw() {
const user = useSelector(state => state.auth.user);
const { id } = useParams();
const id = useBoundaryId();
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice

@mstone121
Copy link
Contributor Author

Does that make sense?

Yep. See changes here: 833ad59.

I'm not going to fixup this commit because it can serve as a refence for undoing manual cache updates.

Copy link
Contributor

@rajadain rajadain left a comment

Choose a reason for hiding this comment

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

+1 tested this is looking good! Nice work guiding this in through all the different reviews!

src/app/src/hooks.js Show resolved Hide resolved
Matt Stone added 8 commits October 20, 2022 12:39
There are two reasons to do this:

The first is that it's less ambiguous than using
`const { id } = useParams()`. This is especially important in deeply
nested components where there are other elements with their own IDs.

Second, if this logic were to change at a later point (perhaps it is
moved into a Context), then it can be updated in one place.
This does not include the back-end changes which will follow in a later
commit.
This could be useful in many components.
This could be useful in many components.
When the query was outside of the <Map> component, it would cause
re-render of the map each time the query data was updated.
These changes are intentionally not fixed up into ff73200 because
it can serve as a reference for how to revere manaual cache updates.
@mstone121 mstone121 merged commit d79070c into develop Oct 20, 2022
@mstone121 mstone121 deleted the ms/save-shape-changes branch October 20, 2022 17:51
mstone121 pushed a commit that referenced this pull request Oct 24, 2022
When #141 was merged, it updated the polygon to read from the RTK query
cache. This broke the add polygon feature and is addressed here.
mstone121 pushed a commit that referenced this pull request Oct 25, 2022
When #141 was merged, it updated the polygon to read from the RTK query
cache. This broke the add polygon feature and is addressed here.
mstone121 pushed a commit that referenced this pull request Oct 25, 2022
When #141 was merged, it updated the polygon to read from the RTK query
cache. This broke the add polygon feature and is addressed here.
mstone121 pushed a commit that referenced this pull request Oct 26, 2022
When #141 was merged, it updated the polygon to read from the RTK query
cache. This broke the add polygon feature and is addressed here.
mstone121 pushed a commit that referenced this pull request Oct 27, 2022
When #141 was merged, it updated the polygon to read from the RTK query
cache. This broke the add polygon feature and is addressed here.
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.

Draw Page: Update Shape When Changed
3 participants