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 @@
- {# .gov override #} + {# .gov override: add headers #} {% if show_changelinks %} diff --git a/src/registrar/templates/admin/base_site.html b/src/registrar/templates/admin/base_site.html index 6b641722f..dcdd29e2f 100644 --- a/src/registrar/templates/admin/base_site.html +++ b/src/registrar/templates/admin/base_site.html @@ -2,6 +2,24 @@ {% load static %} {% load i18n %} +{% block extrahead %} + + + + + +{% endblock %} + {% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} {% block extrastyle %}{{ block.super }} diff --git a/src/registrar/templates/admin/change_form.html b/src/registrar/templates/admin/change_form.html index e0f9ae1a4..78dac9ac0 100644 --- a/src/registrar/templates/admin/change_form.html +++ b/src/registrar/templates/admin/change_form.html @@ -9,4 +9,4 @@ {% endblock %} {% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/registrar/templates/admin/change_form_no_submit.html b/src/registrar/templates/admin/change_form_no_submit.html new file mode 100644 index 000000000..04a491aae --- /dev/null +++ b/src/registrar/templates/admin/change_form_no_submit.html @@ -0,0 +1,20 @@ +{% extends "admin/change_form.html" %} + +{% comment %} Replace the Django ul markup with a div. We'll edit the child markup accordingly in change_form_object_tools {% endcomment %} +{% block object-tools %} +{% if change and not is_popup %} +
+ {% block object-tools-items %} + {{ block.super }} + {% endblock %} +
+{% endif %} +{% endblock %} + +{% block submit_buttons_top %} + {# Do not render the submit buttons #} +{% endblock %} + +{% block submit_buttons_bottom %} + {# Do not render the submit buttons #} +{% endblock %}