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

Location select widget - filter by whether the location "has users" #34912

Merged
merged 10 commits into from
Aug 2, 2024

Conversation

AddisonDunn
Copy link
Contributor

Product Description

Jira.

Part of an epic to add a "has users" setting to organization levels. This particular PR filters the options in the location select dropdown on edit user pages by locations who are allowed to have users.

Changes are behind a FF until the feature's official release.

Technical Summary

Adding an optional argument to the URL for a single boolean felt kinda wrong, I could also have passed a parameter from the widget page, but took the approach of just adding another URL. Open to feedback there.

Feature Flag

LOCATION_HAS_USERS

Safety Assurance

Safety story

  • changes behind a FF
  • Automated tests cover the code
  • Tested briefly locally to make sure nothing was amiss

Automated test coverage

corehq.apps.locations.tests.test_views.LocationSearchViewTest

QA Plan

QA will be done at the end of this feature's dev

Rollback instructions

  • This PR can be reverted after deploy with no further considerations

Labels & Review

  • Risk label is set correctly
  • The set of people pinged as reviewers is appropriate for the level of risk of the change

@AddisonDunn AddisonDunn added the product/feature-flag Change will only affect users who have a specific feature flag enabled label Jul 25, 2024
@AddisonDunn AddisonDunn marked this pull request as ready for review July 25, 2024 16:11
@AddisonDunn
Copy link
Contributor Author

Just remembered backend validation is needed, bear with me

@AddisonDunn AddisonDunn marked this pull request as draft July 25, 2024 16:14
@dimagimon dimagimon added the Risk: High Change affects files that have been flagged as high risk. label Jul 25, 2024
@AddisonDunn AddisonDunn marked this pull request as ready for review July 25, 2024 18:01
corehq/apps/locations/views.py Outdated Show resolved Hide resolved
corehq/apps/locations/views.py Show resolved Hide resolved
delete_all_users()
return super().tearDownClass()

@mock.patch('django_prbac.decorators.has_privilege', return_value=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW there's also a @privilege_enabled decorator you can use for this to target a specific privilege

Comment on lines +34 to +35
url(r'^location_search_has_users_only/$', LocationsSearchView.as_view(
include_locations_with_no_users_allowed=False), name='location_search_has_users_only'),
Copy link
Contributor

Choose a reason for hiding this comment

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

What would you think of naming this after the place it's used rather than what distinguishes it from the other endpoint? We'll also soon be excluding already-assigned locations from the results, so it may see further tweaking.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see from a later commit that the plan is to switch between endpoints depending on the desired functionality. Would it be possible to make this enpdoint specific to the location assignment widget and then move the feature flag check there? Otherwise further changes would need to account for both endpoints.

Copy link
Contributor Author

@AddisonDunn AddisonDunn Jul 30, 2024

Choose a reason for hiding this comment

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

Otherwise further changes would need to account for both endpoints

Why would this be the case? Are you imagining the new needed search criteria with the upcoming location select widget work would be passed as URL parameters? Or maybe your are thinking they could be passed directly to the view, ah. I was thinking they would be passed in the request body. If that's the approach we want to take I am open to that, but maybe changes like you're proposing belong as part of that scope of workk.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I see that it's still the same view in both cases, but with a different initialization parameter here, I was thinking it was a subclass for some reason. I still think there may be a place for making a UserLocationWidgetView and putting the logic there rather than passing it around, but that will probably make more sense with the next bit of deviation from the standard use case than it does now.

Copy link
Contributor

@esoergel esoergel Jul 30, 2024

Choose a reason for hiding this comment

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

I'm struggling a bit to articulate what I'm thinking, but let me try. Essentially, there's a generic "locations select widget" that is used in several different places. This is one customization specific to user location assignment, and we've got a couple more customizations likely coming. The way it's done here is to set a flag on the widget, which directs to a different URL, which sets a flag on the view, which sets a flag on the controller, which forks the behavior in the controller's parent class. That's a lot of steps, making it perhaps challenging to see when/how/why the flag is set to what it is.

The alternative I'm imagining would be to switch from the generic widget to one that's specific to user location assignment. Then it's clear in what context the behavior differs. Perhaps that'd still use the same system of passing flags around, only the flag would be called "is user location assignment" or some such. Then when we fork behavior, we could do it all under the same flag or subclass, making the scope under which those changes apply clearer.

Again I don't think that's necessarily better, certainly not with just this logic change. Mostly leaving my thoughts here now because I suspect it'll start to be more compelling as we further fork the logic (though it's always hard to tell for sure without trying it).

From the article Simon shared this morning:

When designing abstractions, do not prematurely couple behaviours that may evolve separately in the longer term.

Here the widget for picking locations for a user is coupled to the generic widget for finding locations on a project, and I'm thinking that they are starting to evolve separately, so we may want to decouple them (though perhaps the enriched context actually should benefit all instances).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I gotcha. Yeah, what you're saying makes sense.

switch from the generic widget to one that's specific to user location assignment

You mean extending the class to make one thats for assignment to users, right? I agree doing that instead of the "first" flag that's passed through would help clarify to the dev what it's used for/how they should use it. I could also see forking the search view as you're suggesting, into something like UserSelectLocationOptionsView or something like that. I think that's the feel of what you're getting at, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, something like that, whichever seems cleaner. Like maybe it's just a flag in the widget and a subclass for the options view, not sure. But yeah, some way to tie it to the specific usage rather than the behavior change from the "normal" way.

@@ -1141,7 +1141,7 @@ def render(self, name, value, attrs=None, renderer=None):
})


class BaseLocationForm(forms.Form):
class SelectUserLocationForm(forms.Form):
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@@ -72,7 +72,7 @@ def schedule_user_organization_recipients_response(self):
def _get_user_organization_response(self, case_sharing_only=False):
from corehq.apps.locations.views import LocationOptionsController
controller = LocationOptionsController(self.request, self.request.domain,
self.data.get('searchString'), False,
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@AddisonDunn
Copy link
Contributor Author

Bump @esoergel and @Jtang-1 , still ended a final ✅

@AddisonDunn
Copy link
Contributor Author

Thanks @Jtang-1 !

@AddisonDunn AddisonDunn merged commit 4355d4b into master Aug 2, 2024
13 checks passed
@AddisonDunn AddisonDunn deleted the ad/location-has-users-select-widget-filtering branch August 2, 2024 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
product/feature-flag Change will only affect users who have a specific feature flag enabled Risk: High Change affects files that have been flagged as high risk.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants