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

User regions #446

Merged
merged 44 commits into from
Jul 11, 2024
Merged

User regions #446

merged 44 commits into from
Jul 11, 2024

Conversation

BryonLewis
Copy link
Contributor

@BryonLewis BryonLewis commented Jun 10, 2024

resolves #445

  • Adds owner, public fields to a region and model_run. Defaults public to True and owner to None in both instances
  • Condenses the POST endpoint for Region creation to create a region not associated with model run and being bound to a user with the option to make it Public
  • Adds a GET /region/details endpoint to get information about owners and public to the list. This also includes some information about why a user can't delete a region. They are only able to delete regions they own that have all model runs removed from them.
  • Create Region Client Side code. I think I could modify the existing Region button to have an option for 'Add Region' that allows a user to specify a region with name and the public setting.
  • User regions are filters near the top of the region list
  • Added a /regions/{region_id}/vector-tile/z/x/y.pbf endpoint. This is to support visualizing regions when no model-runs are associated with them. This is required to be able to see a region and eventually be able to delete it.
  • Drawing of User Regions has been modified to utilize the new /regions/vector-tile endpoint. I modified region naming so that user regions are indicated by {name}_{userId}. This is for the query selection as well as making sure regions are unique. There are new unique constraints so that the combination of name and owner has to be unique. So now there is a 'value' that is used to indicate a region that is a combination of the name and owner. If the owner is None (it is a system region uploaded by the admin) then it is just the name.
  • I felt it was better to reference the vector-tiles by the region Id instead of the region name. It is still necessary to use the region name for the URL parameters to make it easy to share regions. To facilitate this I added a regionMap to the store to align a region.
  • Redid the Layer Selection of Regions to allow regions to be displayed only if they have geometry associated with them. It also only allows deletion if the user is the owner and no models are linked to the region. If you can't delete it there is a tooltip displaying the reason.
  • I updated model-run endpoint to provide a boundingbox of the region if no model-runs are connected to a region. Previously it would just return a null boundingbox
  • Connected up deletion of region from the interface
  • Moved Region updating to the Store as well as storing of the region list because multiple components need to trigger an update as well as use the values. RegionFilter no longer is the only thing that will cause an update to the region list.
  • Added in basic downloading of a region geojson, right now it sets default values for the custom fields in the region geometry.

@BryonLewis BryonLewis marked this pull request as ready for review July 1, 2024 16:07
@BryonLewis
Copy link
Contributor Author

New Request:
Add the ability to export and download the Region Polygon in geoJSON format.

Copy link
Contributor

@mvandenburgh mvandenburgh left a comment

Choose a reason for hiding this comment

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

Some comments on the python code from an initial look over, I'll test this locally and do a deeper review that includes the frontend changes next.

rdwatch/core/views/model_run.py Outdated Show resolved Hide resolved
rdwatch/core/views/model_run.py Show resolved Hide resolved
Comment on lines 39 to 56
@router.get('/details', response=list[dict])
@paginate(PageNumberPagination, page_size=1000)
def list_region_details(request: HttpRequest):
regions = Region.objects.values_list(
'name', 'owner__username', 'public', 'pk', 'geom'
)
return [
{
'name': region[0],
'owner': region[1] if region[1] is not None else 'None',
'value': region[0] if region[1] is None else f'{region[0]}_{region[1]}',
'public': region[2],
'id': region[3],
'deleteBlock': get_delete_block(region[3], request.user),
'hasGeom': True if region[4] else False,
}
for region in regions
]
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should use a ninja Schema instead of an untyped dict. As it is, it's difficult to parse what's going on with the indexes IMO, and we're also iterating over a queryset when we don't need to. i.e. changing to something like

Suggested change
@router.get('/details', response=list[dict])
@paginate(PageNumberPagination, page_size=1000)
def list_region_details(request: HttpRequest):
regions = Region.objects.values_list(
'name', 'owner__username', 'public', 'pk', 'geom'
)
return [
{
'name': region[0],
'owner': region[1] if region[1] is not None else 'None',
'value': region[0] if region[1] is None else f'{region[0]}_{region[1]}',
'public': region[2],
'id': region[3],
'deleteBlock': get_delete_block(region[3], request.user),
'hasGeom': True if region[4] else False,
}
for region in regions
]
@router.get('/details', response=list[RegionDetailResponseSchema])
@paginate(PageNumberPagination, page_size=1000)
def list_region_details(request: HttpRequest):
regions = Region.objects.values_list(
'name', 'owner__username', 'public', 'pk', 'geom'
)
return regions

Where RegionDetailResponseSchema is defined as needed.

rdwatch/core/views/region.py Outdated Show resolved Hide resolved
Comment on lines 70 to 73
return Response(
{'detail': 'Region model created successfully', 'region_id': str(region.name)},
status=201,
)
Copy link
Contributor

@mvandenburgh mvandenburgh Jul 8, 2024

Choose a reason for hiding this comment

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

It should be possible to simplify this to

Suggested change
return Response(
{'detail': 'Region model created successfully', 'region_id': str(region.name)},
status=201,
)
return 201, {'detail': 'Region model created successfully', 'region_id': str(region.name)}

But, if we want to return structured output that has a detail and region_id field, I think this should be defined as a Schema instead of using a raw Reponse object.

)
# return a successful response for deletion of the region
selected_region.delete()
return JsonResponse({'success': 'Region deleted successfully.'}, status=200)
Copy link
Contributor

Choose a reason for hiding this comment

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

See previous comment about simplifying the response.

selected_region = get_object_or_404(Region, pk=region_id)
if selected_region.owner != owner: # 403 response, only owner can delete a region
return JsonResponse(
{'error': 'You do not have permission to delete this region.'}, status=403
Copy link
Contributor

Choose a reason for hiding this comment

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

See previous comment about simplifying the response.

rdwatch/core/views/region.py Outdated Show resolved Hide resolved
rdwatch/core/views/region.py Outdated Show resolved Hide resolved
@BryonLewis BryonLewis merged commit 09c018f into main Jul 11, 2024
8 checks passed
@BryonLewis BryonLewis deleted the user-regions branch July 11, 2024 11:36
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.

Region Creation
2 participants