mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-16 17:47:02 +02:00
merged (and resolved conflict)
This commit is contained in:
commit
5fd9c02c2e
50 changed files with 1343 additions and 461 deletions
|
@ -37,6 +37,7 @@ from django_admin_multiple_choice_list_filter.list_filters import MultipleChoice
|
|||
from import_export import resources
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
@ -92,6 +93,31 @@ class UserResource(resources.ModelResource):
|
|||
model = models.User
|
||||
|
||||
|
||||
class FilteredSelectMultipleArrayWidget(FilteredSelectMultiple):
|
||||
"""Custom widget to allow for editing an ArrayField in a widget similar to filter_horizontal widget"""
|
||||
|
||||
def __init__(self, verbose_name, is_stacked=False, choices=(), **kwargs):
|
||||
super().__init__(verbose_name, is_stacked, **kwargs)
|
||||
self.choices = choices
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
values = super().value_from_datadict(data, files, name)
|
||||
return values or []
|
||||
|
||||
def get_context(self, name, value, attrs):
|
||||
if value is None:
|
||||
value = []
|
||||
elif isinstance(value, str):
|
||||
value = value.split(",")
|
||||
# alter self.choices to be a list of selected and unselected choices, based on value;
|
||||
# order such that selected choices come before unselected choices
|
||||
self.choices = [(choice, label) for choice, label in self.choices if choice in value] + [
|
||||
(choice, label) for choice, label in self.choices if choice not in value
|
||||
]
|
||||
context = super().get_context(name, value, attrs)
|
||||
return context
|
||||
|
||||
|
||||
class MyUserAdminForm(UserChangeForm):
|
||||
"""This form utilizes the custom widget for its class's ManyToMany UIs.
|
||||
|
||||
|
@ -104,6 +130,14 @@ class MyUserAdminForm(UserChangeForm):
|
|||
widgets = {
|
||||
"groups": NoAutocompleteFilteredSelectMultiple("groups", False),
|
||||
"user_permissions": NoAutocompleteFilteredSelectMultiple("user_permissions", False),
|
||||
"portfolio_roles": FilteredSelectMultipleArrayWidget(
|
||||
"portfolio_roles", is_stacked=False, choices=User.UserPortfolioRoleChoices.choices
|
||||
),
|
||||
"portfolio_additional_permissions": FilteredSelectMultipleArrayWidget(
|
||||
"portfolio_additional_permissions",
|
||||
is_stacked=False,
|
||||
choices=User.UserPortfolioPermissionChoices.choices,
|
||||
),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -654,18 +688,49 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
"is_superuser",
|
||||
"groups",
|
||||
"user_permissions",
|
||||
"portfolio",
|
||||
"portfolio_roles",
|
||||
"portfolio_additional_permissions",
|
||||
)
|
||||
},
|
||||
),
|
||||
("Important dates", {"fields": ("last_login", "date_joined")}),
|
||||
)
|
||||
|
||||
autocomplete_fields = [
|
||||
"portfolio",
|
||||
]
|
||||
|
||||
readonly_fields = ("verification_type",)
|
||||
|
||||
# Hide Username (uuid), Groups and Permissions
|
||||
# Q: Now that we're using Groups and Permissions,
|
||||
# do we expose those to analysts to view?
|
||||
analyst_fieldsets = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
"fields": (
|
||||
"status",
|
||||
"verification_type",
|
||||
)
|
||||
},
|
||||
),
|
||||
("User profile", {"fields": ("first_name", "middle_name", "last_name", "title", "email", "phone")}),
|
||||
(
|
||||
"Permissions",
|
||||
{
|
||||
"fields": (
|
||||
"is_active",
|
||||
"groups",
|
||||
"portfolio",
|
||||
"portfolio_roles",
|
||||
"portfolio_additional_permissions",
|
||||
)
|
||||
},
|
||||
),
|
||||
("Important dates", {"fields": ("last_login", "date_joined")}),
|
||||
)
|
||||
|
||||
# TODO: delete after we merge organization feature
|
||||
analyst_fieldsets_no_portfolio = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
|
@ -712,6 +777,26 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
"Important dates",
|
||||
"last_login",
|
||||
"date_joined",
|
||||
"portfolio",
|
||||
"portfolio_roles",
|
||||
"portfolio_additional_permissions",
|
||||
]
|
||||
|
||||
# TODO: delete after we merge organization feature
|
||||
analyst_readonly_fields_no_portfolio = [
|
||||
"User profile",
|
||||
"first_name",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"title",
|
||||
"email",
|
||||
"phone",
|
||||
"Permissions",
|
||||
"is_active",
|
||||
"groups",
|
||||
"Important dates",
|
||||
"last_login",
|
||||
"date_joined",
|
||||
]
|
||||
|
||||
list_filter = (
|
||||
|
@ -786,8 +871,12 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
# Show all fields for all access users
|
||||
return super().get_fieldsets(request, obj)
|
||||
elif request.user.has_perm("registrar.analyst_access_permission"):
|
||||
# show analyst_fieldsets for analysts
|
||||
return self.analyst_fieldsets
|
||||
if flag_is_active(request, "organization_feature"):
|
||||
# show analyst_fieldsets for analysts
|
||||
return self.analyst_fieldsets
|
||||
else:
|
||||
# TODO: delete after we merge organization feature
|
||||
return self.analyst_fieldsets_no_portfolio
|
||||
else:
|
||||
# any admin user should belong to either full_access_group
|
||||
# or cisa_analyst_group
|
||||
|
@ -801,7 +890,11 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
|||
else:
|
||||
# Return restrictive Read-only fields for analysts and
|
||||
# users who might not belong to groups
|
||||
return self.analyst_readonly_fields
|
||||
if flag_is_active(request, "organization_feature"):
|
||||
return self.analyst_readonly_fields
|
||||
else:
|
||||
# TODO: delete after we merge organization feature
|
||||
return self.analyst_readonly_fields_no_portfolio
|
||||
|
||||
def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||
"""Add user's related domains and requests to context"""
|
||||
|
@ -1004,6 +1097,16 @@ class ContactAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
# Get the filtered values
|
||||
return super().changelist_view(request, extra_context=extra_context)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
# Clear warning messages before saving
|
||||
storage = messages.get_messages(request)
|
||||
storage.used = False
|
||||
for message in storage:
|
||||
if message.level == messages.WARNING:
|
||||
storage.used = True
|
||||
|
||||
return super().save_model(request, obj, form, change)
|
||||
|
||||
|
||||
class SeniorOfficialAdmin(ListHeaderAdmin):
|
||||
"""Custom Senior Official Admin class."""
|
||||
|
@ -1288,10 +1391,11 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
]
|
||||
|
||||
# Readonly fields for analysts and superusers
|
||||
readonly_fields = ("other_contacts", "is_election_board", "federal_agency")
|
||||
readonly_fields = ("other_contacts", "is_election_board")
|
||||
|
||||
# Read only that we'll leverage for CISA Analysts
|
||||
analyst_readonly_fields = [
|
||||
"federal_agency",
|
||||
"creator",
|
||||
"type_of_work",
|
||||
"more_organization_information",
|
||||
|
@ -1604,12 +1708,12 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
"current_websites",
|
||||
"alternative_domains",
|
||||
"is_election_board",
|
||||
"federal_agency",
|
||||
"status_history",
|
||||
)
|
||||
|
||||
# Read only that we'll leverage for CISA Analysts
|
||||
analyst_readonly_fields = [
|
||||
"federal_agency",
|
||||
"creator",
|
||||
"about_your_organization",
|
||||
"requested_domain",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue