diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 4b05bbb6d..8bdebc9fb 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -163,6 +163,18 @@ class MyUserAdminForm(UserChangeForm): "user_permissions": NoAutocompleteFilteredSelectMultiple("user_permissions", False), } + # Loads "tabtitle" for this admin page so that on render the + # element will only have the model name instead of + # the default string loaded by native Django admin code. + # (Eg. instead of "Select contact to change", display "Contacts") + # see "base_site.html" for the <title> code. + def changelist_view(self, request, extra_context=None): + if extra_context is None: + extra_context = {} + extra_context["tabtitle"] = str(self.opts.verbose_name_plural).title() + # Get the filtered values + return super().changelist_view(request, extra_context=extra_context) + def __init__(self, *args, **kwargs): """Custom init to modify the user form""" super(MyUserAdminForm, self).__init__(*args, **kwargs) @@ -523,6 +535,18 @@ class CustomLogEntryAdmin(LogEntryAdmin): "user_url", ] + # Loads "tabtitle" for this admin page so that on render the <title> + # element will only have the model name instead of + # the default string loaded by native Django admin code. + # (Eg. instead of "Select contact to change", display "Contacts") + # see "base_site.html" for the <title> code. + def changelist_view(self, request, extra_context=None): + if extra_context is None: + extra_context = {} + extra_context["tabtitle"] = str(self.opts.verbose_name_plural).title() + # Get the filtered values + return super().changelist_view(request, extra_context=extra_context) + # 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. @@ -542,13 +566,6 @@ class CustomLogEntryAdmin(LogEntryAdmin): change_form_template = "admin/change_form_no_submit.html" add_form_template = "admin/change_form_no_submit.html" - # Select log entry to change -> Log entries - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Log entries" - return super().changelist_view(request, extra_context=extra_context) - # #786: Skipping on updating audit log tab titles for now # def change_view(self, request, object_id, form_url="", extra_context=None): # if extra_context is None: @@ -629,6 +646,18 @@ class AdminSortFields: class AuditedAdmin(admin.ModelAdmin): """Custom admin to make auditing easier.""" + # Loads "tabtitle" for this admin page so that on render the <title> + # element will only have the model name instead of + # the default string loaded by native Django admin code. + # (Eg. instead of "Select contact to change", display "Contacts") + # see "base_site.html" for the <title> code. + def changelist_view(self, request, extra_context=None): + if extra_context is None: + extra_context = {} + extra_context["tabtitle"] = str(self.opts.verbose_name_plural).title() + # Get the filtered values + return super().changelist_view(request, extra_context=extra_context) + def history_view(self, request, object_id, extra_context=None): """On clicking 'History', take admin to the auditlog view for an object.""" return HttpResponseRedirect( @@ -1029,6 +1058,18 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin): extra_context = {"domain_requests": domain_requests, "domains": domains, "portfolios": portfolios} return super().change_view(request, object_id, form_url, extra_context) + # Loads "tabtitle" for this admin page so that on render the <title> + # element will only have the model name instead of + # the default string loaded by native Django admin code. + # (Eg. instead of "Select contact to change", display "Contacts") + # see "base_site.html" for the <title> code. + def changelist_view(self, request, extra_context=None): + if extra_context is None: + extra_context = {} + extra_context["tabtitle"] = str(self.opts.verbose_name_plural).title() + # Get the filtered values + return super().changelist_view(request, extra_context=extra_context) + class HostIPInline(admin.StackedInline): """Edit an ip address on the host page.""" @@ -1053,14 +1094,6 @@ class MyHostAdmin(AuditedAdmin, ImportExportModelAdmin): search_help_text = "Search by domain or host name." inlines = [HostIPInline] - # Select host to change -> Host - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Host" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - class HostIpResource(resources.ModelResource): """defines how each field in the referenced model should be mapped to the corresponding fields in the @@ -1076,14 +1109,6 @@ class HostIpAdmin(AuditedAdmin, ImportExportModelAdmin): resource_classes = [HostIpResource] model = models.HostIP - # Select host ip to change -> Host ip - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Host IP" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - class ContactResource(resources.ModelResource): """defines how each field in the referenced model should be mapped to the corresponding fields in the @@ -1205,14 +1230,6 @@ class ContactAdmin(ListHeaderAdmin, ImportExportModelAdmin): return super().change_view(request, object_id, form_url, extra_context=extra_context) - # Select contact to change -> Contacts - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Contacts" - # 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) @@ -1527,14 +1544,6 @@ class DomainInvitationAdmin(BaseInvitationAdmin): # Override for the delete confirmation page on the domain table (bulk delete action) delete_selected_confirmation_template = "django/admin/domain_invitation_delete_selected_confirmation.html" - # Select domain invitations to change -> Domain invitations - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Domain invitations" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - def change_view(self, request, object_id, form_url="", extra_context=None): """Override the change_view to add the invitation obj for the change_form_object_tools template""" @@ -1673,14 +1682,6 @@ class PortfolioInvitationAdmin(BaseInvitationAdmin): change_form_template = "django/admin/portfolio_invitation_change_form.html" delete_confirmation_template = "django/admin/portfolio_invitation_delete_confirmation.html" - # Select portfolio invitations to change -> Portfolio invitations - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Portfolio invitations" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - def save_model(self, request, obj, form, change): """ Override the save_model method. @@ -2070,14 +2071,6 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin): readonly_fields.extend([field for field in self.analyst_readonly_fields]) return readonly_fields # Read-only fields for analysts - # Select domain information to change -> Domain information - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Domain information" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - def formfield_for_foreignkey(self, db_field, request, **kwargs): """Customize the behavior of formfields with foreign key relationships. This will customize the behavior of selects. Customized behavior includes sorting of objects in list.""" @@ -2898,11 +2891,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): if next_char.isdigit(): should_apply_default_filter = True - # Select domain request to change -> Domain requests - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Domain requests" - if should_apply_default_filter: # modify the GET of the request to set the selected filter modified_get = copy.deepcopy(request.GET) @@ -3959,14 +3947,6 @@ class DraftDomainAdmin(ListHeaderAdmin, ImportExportModelAdmin): # If no redirection is needed, return the original response return response - # Select draft domain to change -> Draft domains - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "Draft domains" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - class PublicContactResource(resources.ModelResource): """defines how each field in the referenced model should be mapped to the corresponding fields in the @@ -4388,14 +4368,6 @@ class UserGroupAdmin(AuditedAdmin): def user_group(self, obj): return obj.name - # Select user groups to change -> User groups - def changelist_view(self, request, extra_context=None): - if extra_context is None: - extra_context = {} - extra_context["tabtitle"] = "User groups" - # Get the filtered values - return super().changelist_view(request, extra_context=extra_context) - class WaffleFlagAdmin(FlagAdmin): """Custom admin implementation of django-waffle's Flag class""" @@ -4412,6 +4384,13 @@ class WaffleFlagAdmin(FlagAdmin): if extra_context is None: extra_context = {} extra_context["dns_prototype_flag"] = flag_is_active_for_user(request.user, "dns_prototype_flag") + + # Loads "tabtitle" for this admin page so that on render the <title> + # element will only have the model name instead of + # the default string loaded by native Django admin code. + # (Eg. instead of "Select waffle flags to change", display "Waffle Flags") + # see "base_site.html" for the <title> code. + extra_context["tabtitle"] = str(self.opts.verbose_name_plural).title() return super().changelist_view(request, extra_context=extra_context) diff --git a/src/registrar/assets/src/sass/_theme/_accordions.scss b/src/registrar/assets/src/sass/_theme/_accordions.scss index 86b8779ab..a4376337d 100644 --- a/src/registrar/assets/src/sass/_theme/_accordions.scss +++ b/src/registrar/assets/src/sass/_theme/_accordions.scss @@ -25,7 +25,6 @@ // Note, width is determined by a custom width class on one of the children position: absolute; z-index: 1; - left: 0; border-radius: 4px; border: solid 1px color('base-lighter'); padding: units(2) units(2) units(3) units(2); @@ -42,6 +41,14 @@ } } +// This will work in responsive tables if we overwrite the overflow value on the table container +// Works with styles in _tables +@include at-media(desktop) { + .usa-accordion--more-actions .usa-accordion__content { + left: 0; + } +} + .usa-accordion--select .usa-accordion__content { top: 33.88px; } @@ -59,10 +66,12 @@ // This won't work on the Members table rows because that table has show-more rows // Currently, that's not an issue since that Members table is not wrapped in the // reponsive wrapper. -tr:last-of-type .usa-accordion--more-actions .usa-accordion__content { - top: auto; - bottom: -10px; - right: 30px; +@include at-media-max("desktop") { + tr:last-of-type .usa-accordion--more-actions .usa-accordion__content { + top: auto; + bottom: -10px; + right: 30px; + } } // A CSS only show-more/show-less based on usa-accordion diff --git a/src/registrar/assets/src/sass/_theme/_base.scss b/src/registrar/assets/src/sass/_theme/_base.scss index 9a1c5d12b..1442acf1f 100644 --- a/src/registrar/assets/src/sass/_theme/_base.scss +++ b/src/registrar/assets/src/sass/_theme/_base.scss @@ -226,11 +226,6 @@ abbr[title] { } } -// Boost this USWDS utility class for the accordions in the portfolio requests table -.left-auto { - left: auto!important; -} - .usa-banner__inner--widescreen { max-width: $widescreen-max-width; } diff --git a/src/registrar/assets/src/sass/_theme/_tables.scss b/src/registrar/assets/src/sass/_theme/_tables.scss index 0e3118126..222f44fcc 100644 --- a/src/registrar/assets/src/sass/_theme/_tables.scss +++ b/src/registrar/assets/src/sass/_theme/_tables.scss @@ -152,3 +152,12 @@ th { .usa-table--full-borderless th { border: none !important; } + +// This is an override to overflow on certain tables (note the custom class) +// so that a popup menu can appear and starddle the edge of the table on large +// screen sizes. Works with styles in _accordions +@include at-media(desktop) { + .usa-table-container--scrollable.usa-table-container--override-overflow { + overflow-y: visible; + } +} diff --git a/src/registrar/templates/admin/analytics.html b/src/registrar/templates/admin/analytics.html index fdebff22c..44578cd59 100644 --- a/src/registrar/templates/admin/analytics.html +++ b/src/registrar/templates/admin/analytics.html @@ -2,6 +2,10 @@ {% load static %} {% load i18n %} +{% block title %} + Registrar Analytics | Django admin +{% endblock %} + {% block content_title %}<h1>Registrar Analytics</h1>{% endblock %} {% block breadcrumbs %} diff --git a/src/registrar/templates/admin/base_site.html b/src/registrar/templates/admin/base_site.html index a8ef438f9..9b7bb5887 100644 --- a/src/registrar/templates/admin/base_site.html +++ b/src/registrar/templates/admin/base_site.html @@ -33,8 +33,8 @@ {{ tabtitle }} | {% else %} {{ title }} | - {% endif %} - {{ site_title|default:_('Django site admin') }} + {% endif %} + Django admin {% endblock %} {% block extrastyle %}{{ block.super }} diff --git a/src/registrar/templates/domain_org_name_address.html b/src/registrar/templates/domain_org_name_address.html index 0785b6da1..956ec084b 100644 --- a/src/registrar/templates/domain_org_name_address.html +++ b/src/registrar/templates/domain_org_name_address.html @@ -29,7 +29,10 @@ {% csrf_token %} {% if domain.domain_info.generic_org_type == 'federal' %} - {% input_with_errors form.federal_agency %} + <h4 class="margin-bottom-05">Federal Agency</h4> + <p class="margin-top-0"> + {{ domain.domain_info.federal_agency }} + </p> {% endif %} {% input_with_errors form.organization_name %} diff --git a/src/registrar/templates/includes/domain_requests_table.html b/src/registrar/templates/includes/domain_requests_table.html index 8adc0929a..df6b12828 100644 --- a/src/registrar/templates/includes/domain_requests_table.html +++ b/src/registrar/templates/includes/domain_requests_table.html @@ -163,7 +163,7 @@ </div> {% endif %} - <div class="display-none usa-table-container--scrollable margin-top-0" tabindex="0" id="domain-requests__table-wrapper"> + <div class="display-none usa-table-container--scrollable usa-table-container--override-overflow margin-top-0" tabindex="0" id="domain-requests__table-wrapper"> <table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked"> <caption class="sr-only">Your domain requests</caption> <thead> diff --git a/src/registrar/templates/includes/domains_table.html b/src/registrar/templates/includes/domains_table.html index 3cf04a830..f7e47bbbc 100644 --- a/src/registrar/templates/includes/domains_table.html +++ b/src/registrar/templates/includes/domains_table.html @@ -198,7 +198,7 @@ </svg> </button> </div> - <div class="display-none usa-table-container--scrollable margin-top-0" tabindex="0" id="domains__table-wrapper"> + <div class="display-none usa-table-container--scrollable usa-table-container--override-overflow margin-top-0" tabindex="0" id="domains__table-wrapper"> <table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked"> <caption class="sr-only">Your registered domains</caption> <thead> diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py index 80a98fc80..940fe29bf 100644 --- a/src/registrar/tests/test_views_domain.py +++ b/src/registrar/tests/test_views_domain.py @@ -2088,62 +2088,6 @@ class TestDomainOrganization(TestDomainOverview): # Check for the value we want to update self.assertContains(success_result_page, "Faketown") - @less_console_noise_decorator - def test_domain_org_name_address_form_federal(self): - """ - Submitting a change to federal_agency is blocked for federal domains - """ - - fed_org_type = DomainInformation.OrganizationChoices.FEDERAL - self.domain_information.generic_org_type = fed_org_type - self.domain_information.save() - try: - federal_agency, _ = FederalAgency.objects.get_or_create(agency="AMTRAK") - self.domain_information.federal_agency = federal_agency - self.domain_information.save() - except ValueError as err: - self.fail(f"A ValueError was caught during the test: {err}") - - self.assertEqual(self.domain_information.generic_org_type, fed_org_type) - - org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id})) - - form = org_name_page.forms[0] - # Check the value of the input field - agency_input = form.fields["federal_agency"][0] - self.assertEqual(agency_input.value, str(federal_agency.id)) - - # Check if the input field is disabled - self.assertTrue("disabled" in agency_input.attrs) - self.assertEqual(agency_input.attrs.get("disabled"), "") - - session_id = self.app.cookies[settings.SESSION_COOKIE_NAME] - - org_name_page.form["federal_agency"] = FederalAgency.objects.filter(agency="Department of State").get().id - org_name_page.form["city"] = "Faketown" - - self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id) - - # Make the change. The agency should be unchanged, but city should be modifiable. - success_result_page = org_name_page.form.submit() - self.assertEqual(success_result_page.status_code, 200) - - # Check that the agency has not changed - self.assertEqual(self.domain_information.federal_agency.agency, "AMTRAK") - - # Do another check on the form itself - form = success_result_page.forms[0] - # Check the value of the input field - organization_name_input = form.fields["federal_agency"][0] - self.assertEqual(organization_name_input.value, str(federal_agency.id)) - - # Check if the input field is disabled - self.assertTrue("disabled" in organization_name_input.attrs) - self.assertEqual(organization_name_input.attrs.get("disabled"), "") - - # Check for the value we want to update - self.assertContains(success_result_page, "Faketown") - @less_console_noise_decorator def test_federal_agency_submit_blocked(self): """