Merge branch 'main' into za/1864-error-message-rejection-placement

This commit is contained in:
zandercymatics 2024-03-20 08:18:27 -06:00
commit fb6b8838d3
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
69 changed files with 3252 additions and 760 deletions

View file

@ -1,10 +1,11 @@
from datetime import date
import logging
import copy
from django import forms
from django.db.models.functions import Concat, Coalesce
from django.db.models import Value, CharField, Q
from django.http import HttpResponse, HttpResponseRedirect
from django.db.models.functions import Concat, Coalesce
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from django_fsm import get_available_FIELD_transitions
from django.contrib import admin, messages
@ -875,18 +876,21 @@ class DomainInformationAdmin(ListHeaderAdmin):
search_help_text = "Search by domain."
fieldsets = [
(None, {"fields": ["creator", "domain_request", "notes"]}),
(None, {"fields": ["creator", "submitter", "domain_request", "notes"]}),
(".gov domain", {"fields": ["domain"]}),
("Contacts", {"fields": ["authorizing_official", "other_contacts", "no_other_contacts_rationale"]}),
("Background info", {"fields": ["anything_else"]}),
(
"Type of organization",
{
"fields": [
"organization_type",
"is_election_board",
"federal_type",
"federal_agency",
"tribe_name",
"federally_recognized_tribe",
"state_recognized_tribe",
"tribe_name",
"federal_agency",
"federal_type",
"is_election_board",
"about_your_organization",
]
},
@ -896,28 +900,15 @@ class DomainInformationAdmin(ListHeaderAdmin):
{
"fields": [
"organization_name",
"state_territory",
"address_line1",
"address_line2",
"city",
"state_territory",
"zipcode",
"urbanization",
]
},
),
("Authorizing official", {"fields": ["authorizing_official"]}),
(".gov domain", {"fields": ["domain"]}),
("Your contact information", {"fields": ["submitter"]}),
("Other employees from your organization?", {"fields": ["other_contacts"]}),
(
"No other employees from your organization?",
{"fields": ["no_other_contacts_rationale"]},
),
("Anything else?", {"fields": ["anything_else"]}),
(
"Requirements for operating a .gov domain",
{"fields": ["is_policy_acknowledged"]},
),
]
# Read only that we'll leverage for CISA Analysts
@ -1029,6 +1020,8 @@ class DomainRequestAdmin(ListHeaderAdmin):
if self.value() == "0":
return queryset.filter(Q(is_election_board=False) | Q(is_election_board=None))
change_form_template = "django/admin/domain_application_change_form.html"
# Columns
list_display = [
"requested_domain",
@ -1040,7 +1033,7 @@ class DomainRequestAdmin(ListHeaderAdmin):
"custom_election_board",
"city",
"state_territory",
"created_at",
"submission_date",
"submitter",
"investigator",
]
@ -1077,18 +1070,34 @@ class DomainRequestAdmin(ListHeaderAdmin):
search_help_text = "Search by domain or submitter."
fieldsets = [
(None, {"fields": ["status", "rejection_reason", "investigator", "creator", "approved_domain", "notes"]}),
(
None,
{
"fields": [
"status",
"rejection_reason",
"investigator",
"creator",
"submitter",
"approved_domain",
"notes",
]
},
),
(".gov domain", {"fields": ["requested_domain", "alternative_domains"]}),
("Contacts", {"fields": ["authorizing_official", "other_contacts", "no_other_contacts_rationale"]}),
("Background info", {"fields": ["purpose", "anything_else", "current_websites"]}),
(
"Type of organization",
{
"fields": [
"organization_type",
"is_election_board",
"federal_type",
"federal_agency",
"tribe_name",
"federally_recognized_tribe",
"state_recognized_tribe",
"tribe_name",
"federal_agency",
"federal_type",
"is_election_board",
"about_your_organization",
]
},
@ -1098,30 +1107,15 @@ class DomainRequestAdmin(ListHeaderAdmin):
{
"fields": [
"organization_name",
"state_territory",
"address_line1",
"address_line2",
"city",
"state_territory",
"zipcode",
"urbanization",
]
},
),
("Authorizing official", {"fields": ["authorizing_official"]}),
("Current websites", {"fields": ["current_websites"]}),
(".gov domain", {"fields": ["requested_domain", "alternative_domains"]}),
("Purpose of your domain", {"fields": ["purpose"]}),
("Your contact information", {"fields": ["submitter"]}),
("Other employees from your organization?", {"fields": ["other_contacts"]}),
(
"No other employees from your organization?",
{"fields": ["no_other_contacts_rationale"]},
),
("Anything else?", {"fields": ["anything_else"]}),
(
"Requirements for operating a .gov domain",
{"fields": ["is_policy_acknowledged"]},
),
]
# Read only that we'll leverage for CISA Analysts
@ -1353,7 +1347,13 @@ class DomainInformationInline(admin.StackedInline):
model = models.DomainInformation
fieldsets = DomainInformationAdmin.fieldsets
fieldsets = copy.deepcopy(DomainInformationAdmin.fieldsets)
# remove .gov domain from fieldset
for index, (title, f) in enumerate(fieldsets):
if title == ".gov domain":
del fieldsets[index]
break
analyst_readonly_fields = DomainInformationAdmin.analyst_readonly_fields
# For each filter_horizontal, init in admin js extendFilterHorizontalWidgets
# to activate the edit/delete/view buttons
@ -1490,12 +1490,25 @@ class DomainAdmin(ListHeaderAdmin):
search_fields = ["name"]
search_help_text = "Search by domain name."
change_form_template = "django/admin/domain_change_form.html"
change_list_template = "django/admin/domain_change_list.html"
readonly_fields = ["state", "expiration_date", "first_ready", "deleted"]
# Table ordering
ordering = ["name"]
# Override for the delete confirmation page on the domain table (bulk delete action)
delete_selected_confirmation_template = "django/admin/domain_delete_selected_confirmation.html"
def delete_view(self, request, object_id, extra_context=None):
"""
Custom delete_view to perform additional actions or customize the template.
"""
# Set the delete template to a custom one
self.delete_confirmation_template = "django/admin/domain_delete_confirmation.html"
response = super().delete_view(request, object_id, extra_context=extra_context)
return response
def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
"""Custom changeform implementation to pass in context information"""
if extra_context is None:
@ -1523,56 +1536,6 @@ class DomainAdmin(ListHeaderAdmin):
return super().changeform_view(request, object_id, form_url, extra_context)
def export_data_type(self, request):
# match the CSV example with all the fields
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="domains-by-type.csv"'
csv_export.export_data_type_to_csv(response)
return response
def export_data_full(self, request):
# Smaller export based on 1
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="current-full.csv"'
csv_export.export_data_full_to_csv(response)
return response
def export_data_federal(self, request):
# Federal only
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="current-federal.csv"'
csv_export.export_data_federal_to_csv(response)
return response
def get_urls(self):
from django.urls import path
urlpatterns = super().get_urls()
# Used to extrapolate a path name, for instance
# name="{app_label}_{model_name}_export_data_type"
info = self.model._meta.app_label, self.model._meta.model_name
my_url = [
path(
"export_data_type/",
self.export_data_type,
name="%s_%s_export_data_type" % info,
),
path(
"export_data_full/",
self.export_data_full,
name="%s_%s_export_data_full" % info,
),
path(
"export_data_federal/",
self.export_data_federal,
name="%s_%s_export_data_federal" % info,
),
]
return my_url + urlpatterns
def response_change(self, request, obj):
# Create dictionary of action functions
ACTION_FUNCTIONS = {
@ -1704,9 +1667,11 @@ class DomainAdmin(ListHeaderAdmin):
else:
self.message_user(
request,
"Error deleting this Domain: "
f"Can't switch from state '{obj.state}' to 'deleted'"
", must be either 'dns_needed' or 'on_hold'",
(
"Error deleting this Domain: "
f"Can't switch from state '{obj.state}' to 'deleted'"
", must be either 'dns_needed' or 'on_hold'"
),
messages.ERROR,
)
except Exception:
@ -1718,7 +1683,7 @@ class DomainAdmin(ListHeaderAdmin):
else:
self.message_user(
request,
("Domain %s has been deleted. Thanks!") % obj.name,
"Domain %s has been deleted. Thanks!" % obj.name,
)
return HttpResponseRedirect(".")
@ -1760,7 +1725,7 @@ class DomainAdmin(ListHeaderAdmin):
else:
self.message_user(
request,
("%s is in client hold. This domain is no longer accessible on the public internet.") % obj.name,
"%s is in client hold. This domain is no longer accessible on the public internet." % obj.name,
)
return HttpResponseRedirect(".")
@ -1789,7 +1754,7 @@ class DomainAdmin(ListHeaderAdmin):
else:
self.message_user(
request,
("%s is ready. This domain is accessible on the public internet.") % obj.name,
"%s is ready. This domain is accessible on the public internet." % obj.name,
)
return HttpResponseRedirect(".")
@ -1834,9 +1799,6 @@ class VerifiedByStaffAdmin(ListHeaderAdmin):
list_display = ("email", "requestor", "truncated_notes", "created_at")
search_fields = ["email"]
search_help_text = "Search by email."
list_filter = [
"requestor",
]
readonly_fields = [
"requestor",
]