Convert investigator id to investigator name in descriptive subheader on admin lists, update unit test, linting

This commit is contained in:
rachidatecs 2023-07-06 13:57:27 -04:00
parent 257db0fae5
commit 10b0700657
No known key found for this signature in database
GPG key ID: 3CEBBFA7325E5525
5 changed files with 81 additions and 21 deletions

View file

@ -41,20 +41,48 @@ class ListHeaderAdmin(AuditedAdmin):
return super().changelist_view(request, extra_context=extra_context)
def get_filters(self, request):
"""Retrieve the current set of parameters being used to filter the table
Returns:
dictionary objects in the format {parameter_name: string,
parameter_value: string}
TODO: convert investigator id to investigator username
"""
filters = []
# Retrieve the filter parameters
for param in request.GET.keys():
# Exclude the default search parameter 'q'
if param != "q" and param != "o":
# Append the filter parameter and its value to the list
filters.append(
{
"parameter_name": param.replace("__exact", "")
.replace("_type", "")
.replace("__id", " id"),
"parameter_value": request.GET.get(param),
}
parameter_name = (
param.replace("__exact", "")
.replace("_type", "")
.replace("__id", " id")
)
if parameter_name == "investigator id":
# Retrieves the corresponding contact from Users
id_value = request.GET.get(param)
try:
contact = models.User.objects.get(id=id_value)
investigator_name = contact.first_name + " " + contact.last_name
filters.append(
{
"parameter_name": "investigator",
"parameter_value": investigator_name,
}
)
except models.User.DoesNotExist:
pass
else:
# For other parameter names, append a dictionary with the original
# parameter_name and the corresponding parameter_value
filters.append(
{
"parameter_name": parameter_name,
"parameter_value": request.GET.get(param),
}
)
return filters
@ -128,6 +156,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
"""Customize the applications listing view."""
# Columns
list_display = [
"requested_domain",
"status",
@ -136,7 +165,11 @@ class DomainApplicationAdmin(ListHeaderAdmin):
"submitter",
"investigator",
]
# Filters
list_filter = ("status", "organization_type", "investigator")
# Search
search_fields = [
"requested_domain__name",
"submitter__email",
@ -144,6 +177,8 @@ class DomainApplicationAdmin(ListHeaderAdmin):
"submitter__last_name",
]
search_help_text = "Search by domain or submitter."
# Detail view
fieldsets = [
(None, {"fields": ["status", "investigator", "creator"]}),
(
@ -192,6 +227,8 @@ class DomainApplicationAdmin(ListHeaderAdmin):
{"fields": ["is_policy_acknowledged"]},
),
]
# Read only that we'll leverage for CISA Analysts
readonly_fields = [
"creator",
"type_of_work",
@ -240,7 +277,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
# Superusers have full access, no fields are read-only
return ()
return []
else:
# Regular users can only view the specified fields
return self.readonly_fields

View file

@ -91,11 +91,11 @@ INSTALLED_APPS = [
# vv Required by django.contrib.admin vv
# the "user" model! *\o/*
"django.contrib.auth",
# generic interface for Django models
"auditlog",
# library to simplify form templating
# audit logging of changes to models
# it needs to be listed before django.contrib.contenttypes
# for a ContentType query in fixtures.py
"auditlog",
# generic interface for Django models
"django.contrib.contenttypes",
# required for CSRF protection and many other things
"django.contrib.sessions",
@ -108,7 +108,7 @@ INSTALLED_APPS = [
"django.contrib.staticfiles",
# application used for integrating with Login.gov
"djangooidc",
# audit logging of changes to models
# library to simplify form templating
"widget_tweaks",
# library for Finite State Machine statuses
"django_fsm",

View file

@ -65,6 +65,11 @@ class UserFixture:
"first_name": "Rachid-Analyst",
"last_name": "Mrad-Analyst",
},
{
"username": "b6a15987-5c88-4e26-8de2-ca71a0bdb2cd",
"first_name": "Alysia-Analyst",
"last_name": "Alysia-Analyst",
},
]
STAFF_PERMISSIONS = [
@ -99,7 +104,7 @@ class UserFixture:
logger.debug("User object created for %s" % admin["first_name"])
except Exception as e:
logger.warning(e)
logger.debug("All superusers loaded.")
logger.info("All superusers loaded.")
logger.info("Going to load %s CISA analysts (staff)" % str(len(cls.STAFF)))
for staff in cls.STAFF:
@ -150,7 +155,7 @@ class UserFixture:
logger.debug("User object created for %s" % staff["first_name"])
except Exception as e:
logger.warning(e)
logger.debug("All CISA analysts (staff) loaded.")
logger.info("All CISA analysts (staff) loaded.")
class DomainApplicationFixture:

View file

@ -8,7 +8,7 @@ from typing import List, Dict
from django.conf import settings
from django.contrib.auth import get_user_model, login
from registrar.models import Contact, DraftDomain, Website, DomainApplication
from registrar.models import Contact, DraftDomain, Website, DomainApplication, User
def get_handlers():
@ -157,3 +157,17 @@ def completed_application(
application.alternative_domains.add(alt)
return application
def mock_user():
"""A simple user."""
user_kwargs = dict(
id = 4,
first_name = "Rachid",
last_name = "Mrad",
)
user, _ = User.objects.get_or_create(
**user_kwargs
)
return user

View file

@ -2,7 +2,7 @@ from django.test import TestCase, RequestFactory, Client
from django.contrib.admin.sites import AdminSite
from registrar.admin import DomainApplicationAdmin, ListHeaderAdmin
from registrar.models import DomainApplication, DomainInformation, User
from .common import completed_application
from .common import completed_application, mock_user
from django.contrib.auth import get_user_model
from django.conf import settings
@ -184,12 +184,15 @@ class TestDomainApplicationAdmin(TestCase):
p = "adminpassword"
self.client.login(username="admin", password=p)
# Mock a user
user = mock_user()
# Make the request using the Client class
# which handles CSRF
# Follow=True handles the redirect
response = self.client.get(
"/admin/registrar/domainapplication/",
{"status__exact": "started", "investigator__id__exact": "4", "q": "Hello"},
{"status__exact": "started", "investigator__id__exact": user.id, "q": "Hello"},
follow=True,
)
@ -204,7 +207,7 @@ class TestDomainApplicationAdmin(TestCase):
filters,
[
{"parameter_name": "status", "parameter_value": "started"},
{"parameter_name": "investigator id", "parameter_value": "4"},
{"parameter_name": "investigator", "parameter_value": user.first_name + " " + user.last_name},
],
)
@ -212,7 +215,7 @@ class TestDomainApplicationAdmin(TestCase):
# Create a mock request object
request = self.factory.get("/admin/yourmodel/")
# Set the GET parameters for testing
request.GET = {"status": "started", "investigator id": "4", "q": "search_value"}
request.GET = {"status": "started", "investigator": "Rachid Mrad", "q": "search_value"}
# Call the get_filters method
filters = self.admin.get_filters(request)
@ -221,11 +224,12 @@ class TestDomainApplicationAdmin(TestCase):
filters,
[
{"parameter_name": "status", "parameter_value": "started"},
{"parameter_name": "investigator id", "parameter_value": "4"},
{"parameter_name": "investigator", "parameter_value": "Rachid Mrad"},
],
)
def tearDown(self):
# delete any applications too
DomainApplication.objects.all().delete()
User.objects.all().delete()
self.superuser.delete()