diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 1427cb054..af487bd78 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -6,10 +6,36 @@ from django.urls import reverse from registrar.models.utility.admin_sort_fields import AdminSortFields from . import models +from auditlog.models import LogEntry # type: ignore +from auditlog.admin import LogEntryAdmin # type: ignore logger = logging.getLogger(__name__) +class CustomLogEntryAdmin(LogEntryAdmin): + """Overwrite the generated LogEntry admin class""" + + list_display = [ + "created", + "resource", + "action", + "msg_short", + "user_url", + ] + + # We name the custom prop 'resource' because linter + # is not allowing a short_description attr on it + # This gets around the linter limitation, for now. + def resource(self, obj): + # Return the field value without a link + return f"{obj.content_type} - {obj.object_repr}" + + search_help_text = "Search by resource, changes, or user." + + change_form_template = "admin/change_form_no_submit.html" + add_form_template = "admin/change_form_no_submit.html" + + class AuditedAdmin(admin.ModelAdmin, AdminSortFields): """Custom admin to make auditing easier.""" @@ -91,14 +117,12 @@ def get_filters(self, request): class UserContactInline(admin.StackedInline): - """Edit a user's profile on the user page.""" model = models.Contact class MyUserAdmin(BaseUserAdmin): - """Custom user admin class to use our inlines.""" inlines = [UserContactInline] @@ -152,23 +176,37 @@ def get_fieldsets(self, request, obj=None): class HostIPInline(admin.StackedInline): - """Edit an ip address on the host page.""" model = models.HostIP class MyHostAdmin(AuditedAdmin): - """Custom host admin class to use our inlines.""" inlines = [HostIPInline] class DomainAdmin(ListHeaderAdmin): - """Custom domain admin class to add extra buttons.""" + # Columns + list_display = [ + "name", + "organization_type", + "state", + ] + + def organization_type(self, obj): + return obj.domain_info.organization_type + + organization_type.admin_order_field = ( # type: ignore + "domain_info__organization_type" + ) + + # Filters + list_filter = ["domain_info__organization_type"] + search_fields = ["name"] search_help_text = "Search by domain name." change_form_template = "django/admin/domain_change_form.html" @@ -250,11 +288,100 @@ class ContactAdmin(ListHeaderAdmin): search_fields = ["email", "first_name", "last_name"] search_help_text = "Search by firstname, lastname or email." + list_display = [ + "contact", + "email", + ] + + # We name the custom prop 'contact' because linter + # is not allowing a short_description attr on it + # This gets around the linter limitation, for now. + def contact(self, obj: models.Contact): + """Duplicate the contact _str_""" + if obj.first_name or obj.last_name: + return obj.get_formatted_name() + elif obj.email: + return obj.email + elif obj.pk: + return str(obj.pk) + else: + return "" + + contact.admin_order_field = "first_name" # type: ignore + + +class WebsiteAdmin(ListHeaderAdmin): + """Custom website admin class.""" + + # Search + search_fields = [ + "website", + ] + search_help_text = "Search by website." + + +class UserDomainRoleAdmin(ListHeaderAdmin): + """Custom domain role admin class.""" + + # Columns + list_display = [ + "user", + "domain", + "role", + ] + + # Search + search_fields = [ + "user__first_name", + "user__last_name", + "domain__name", + "role", + ] + search_help_text = "Search by user, domain, or role." + + +class DomainInvitationAdmin(ListHeaderAdmin): + """Custom domain invitation admin class.""" + + # Columns + list_display = [ + "email", + "domain", + "status", + ] + + # Search + search_fields = [ + "email", + "domain__name", + ] + search_help_text = "Search by email or domain." + + +class DomainInformationAdmin(ListHeaderAdmin): + """Customize domain information admin class.""" + + # Columns + list_display = [ + "domain", + "organization_type", + "created_at", + "submitter", + ] + + # Filters + list_filter = ["organization_type"] + + # Search + search_fields = [ + "domain__name", + ] + search_help_text = "Search by domain." class DomainApplicationAdmin(ListHeaderAdmin): - """Customize the applications listing view.""" + """Custom domain applications admin class.""" # Set multi-selects 'read-only' (hide selects and show data) # based on user perms and application creator's status @@ -428,14 +555,16 @@ def change_view(self, request, object_id, form_url="", extra_context=None): return super().change_view(request, object_id, form_url, extra_context) +admin.site.unregister(LogEntry) # Unregister the default registration +admin.site.register(LogEntry, CustomLogEntryAdmin) admin.site.register(models.User, MyUserAdmin) -admin.site.register(models.UserDomainRole, AuditedAdmin) +admin.site.register(models.UserDomainRole, UserDomainRoleAdmin) admin.site.register(models.Contact, ContactAdmin) -admin.site.register(models.DomainInvitation, AuditedAdmin) -admin.site.register(models.DomainInformation, AuditedAdmin) +admin.site.register(models.DomainInvitation, DomainInvitationAdmin) +admin.site.register(models.DomainInformation, DomainInformationAdmin) admin.site.register(models.Domain, DomainAdmin) admin.site.register(models.Host, MyHostAdmin) admin.site.register(models.Nameserver, MyHostAdmin) -admin.site.register(models.Website, AuditedAdmin) +admin.site.register(models.Website, WebsiteAdmin) admin.site.register(models.DomainApplication, DomainApplicationAdmin) admin.site.register(models.TransitionDomain, AuditedAdmin) diff --git a/src/registrar/assets/sass/_theme/_admin.scss b/src/registrar/assets/sass/_theme/_admin.scss index 3f594dac7..a2e32bd21 100644 --- a/src/registrar/assets/sass/_theme/_admin.scss +++ b/src/registrar/assets/sass/_theme/_admin.scss @@ -31,7 +31,7 @@ html[data-theme="light"] { // #{$theme-link-color} would interpolate to 'primary', so we use the source value instead --link-fg: #{$theme-color-primary}; - --link-hover-color: #{$theme-color-primary-darker}; + --link-hover-color: #{$theme-color-primary}; // $theme-link-visited-color - violet-70v --link-selected-fg: #54278f; @@ -153,9 +153,12 @@ h1, h2, h3 { padding-top: 20px; } -// 'Delete button' layout bug -.submit-row a.deletelink { +// Fix django admin button height bugs +.submit-row a.deletelink, +.delete-confirmation form .cancel-link, +.submit-row a.closelink { height: auto!important; + font-size: 14px; } // Keep th from collapsing diff --git a/src/registrar/templates/admin/app_list.html b/src/registrar/templates/admin/app_list.html index 40789579c..1c7f6007f 100644 --- a/src/registrar/templates/admin/app_list.html +++ b/src/registrar/templates/admin/app_list.html @@ -5,7 +5,7 @@