diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js index f38afd252..702364cba 100644 --- a/src/registrar/assets/js/get-gov-admin.js +++ b/src/registrar/assets/js/get-gov-admin.js @@ -394,3 +394,38 @@ function initializeWidgetOnList(list, parentId) { observer.observe(targetElement); } })(); + +/** An IIFE for toggling the overflow styles on django-admin__model-description (the show more / show less button) */ +(function () { + function handleShowMoreButton(toggleButton, descriptionDiv){ + // Check the length of the text content in the description div + if (descriptionDiv.textContent.length < 200) { + // Hide the toggle button if text content is less than 200 characters + // This is a little over 160 characters to give us some wiggle room if we + // change the font size marginally. + toggleButton.classList.add('display-none'); + } else { + toggleButton.addEventListener('click', function() { + toggleShowMoreButton(toggleButton, descriptionDiv, 'dja__model-description--no-overflow') + }); + } + } + + function toggleShowMoreButton(toggleButton, descriptionDiv, showMoreClassName){ + // Toggle the class on the description div + descriptionDiv.classList.toggle(showMoreClassName); + + // Change the button text based on the presence of the class + if (descriptionDiv.classList.contains(showMoreClassName)) { + toggleButton.textContent = 'Show less'; + } else { + toggleButton.textContent = 'Show more'; + } + } + + let toggleButton = document.getElementById('dja-show-more-model-description'); + let descriptionDiv = document.querySelector('.dja__model-description'); + if (toggleButton && descriptionDiv) { + handleShowMoreButton(toggleButton, descriptionDiv) + } +})(); diff --git a/src/registrar/assets/sass/_theme/_admin.scss b/src/registrar/assets/sass/_theme/_admin.scss index b4b590acb..b4b5c657d 100644 --- a/src/registrar/assets/sass/_theme/_admin.scss +++ b/src/registrar/assets/sass/_theme/_admin.scss @@ -676,3 +676,35 @@ form .aligned p.help, form .aligned div.help { background: var(--primary); color: var(--header-link-color); } + +div.dja__model-description{ + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + + p, li { + font-size: medium; + color: var(--secondary); + } + + li { + list-style-type: disc; + font-family: Source Sans Pro Web,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif; + } + + a, a:link, a:visited { + font-size: medium; + color: #005288 !important; + } + + &.dja__model-description--no-overflow { + display: block; + overflow: auto; + } + +} + +.text-underline { + text-decoration: underline !important; +} diff --git a/src/registrar/templates/admin/change_list.html b/src/registrar/templates/admin/change_list.html index 05c2d4e64..43abf0861 100644 --- a/src/registrar/templates/admin/change_list.html +++ b/src/registrar/templates/admin/change_list.html @@ -2,6 +2,10 @@ {% block content_title %}
This table does not have a description yet.
+ {% endif %} ++Contacts include anyone who has access to the registrar (known as “users”) and anyone listed in a domain request, +including other employees and authorizing officials. +Only contacts who have access to the registrar will have +a corresponding record within the Users table. +
+ ++Updating someone’s contact information here will not affect that person’s Login.gov information. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/domain_description.html b/src/registrar/templates/django/admin/includes/descriptions/domain_description.html new file mode 100644 index 000000000..5b8a79a4a --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/domain_description.html @@ -0,0 +1,25 @@ ++This table contains all approved domains in the .gov registrar. +In other words, with the exception of domains in the “Unknown”, ”On hold”, and “Deleted” states, +this table matches the list of domains in the .gov zone file. +
+ ++Individual domain pages allow you to view registry-related details and edit the associated domain information. +
+ ++Other actions available on the domain page include the ability to: +
++To view a domain from a domain manager’s perspective, click the "Manage domain" button. +That will allow you to make changes (e.g., update DNS settings, invite people to manage the domain) +directly inside the registrar. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/domain_information_description.html b/src/registrar/templates/django/admin/includes/descriptions/domain_information_description.html new file mode 100644 index 000000000..36d197cf8 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/domain_information_description.html @@ -0,0 +1,19 @@ ++Domain information represents the basic metadata for an approved domain and the organization that manages it. +It does not include any information specific to the registry (DNS name servers, security email). +Registry-related information +can be managed within the Domains table. +
+ ++Updating values here will immediately update the corresponding values that users see in the registrar. +
+ ++Domain information is similar to Domain requests, +and the fields are nearly identical, +but edits made to one are not made to the other. +Domain information exists so we don’t modify details of an approved request after adjudication +(since a domain request should be maintained as-adjudicated for records retention purposes). +Entries are created here upon approval of a domain request. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/domain_invitation_description.html b/src/registrar/templates/django/admin/includes/descriptions/domain_invitation_description.html new file mode 100644 index 000000000..7765b9203 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/domain_invitation_description.html @@ -0,0 +1,16 @@ ++Domain invitations contain all individuals who have been invited to manage a .gov domain. +Invitations are sent via email, and the recipient must log in to the registrar to officially +accept and become a domain manager. +
+ ++An “invited” status indicates that the recipient has not logged in to the registrar since the invitation was sent. +A “received” status indicates that the recipient has logged in. +
+ ++If an invitation is created in this table, an email will not be sent. +To have an email sent, go to the domain in Domains, +click the “Manage domain” button, and add a domain manager. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/domain_request_description.html b/src/registrar/templates/django/admin/includes/descriptions/domain_request_description.html new file mode 100644 index 000000000..5adc07454 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/domain_request_description.html @@ -0,0 +1,11 @@ ++This table contains all domain requests that have been started within the registrar and the status of those requests. +Updating values here will immediately update the corresponding values that users see in the registrar. +
+ ++Once a domain request has been adjudicated, the details of that request should not be modified. +To update attributes (like an organization’s name) after a domain’s approval, +go to Domains. +Similar fields display on each Domain page, but edits made there will not affect the corresponding domain request. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/draft_domain_description.html b/src/registrar/templates/django/admin/includes/descriptions/draft_domain_description.html new file mode 100644 index 000000000..9e0ac9914 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/draft_domain_description.html @@ -0,0 +1,10 @@ ++This table represents all “requested domains” that have been saved within a domain request form. +If a registrant changes the requested domain in their form, +the original name they listed and the new name will appear as separate records. +
+ ++This table does not include “alternative domains,” +which are housed in the Websites table. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/host_description.html b/src/registrar/templates/django/admin/includes/descriptions/host_description.html new file mode 100644 index 000000000..a39519898 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/host_description.html @@ -0,0 +1,11 @@ ++Entries in the Hosts table indicate the relationship between an approved domain and a name server address +(and, if applicable, the IP address for a name server address). +
+ ++In general, you should not modify these values here. They should be updated directly inside the registrar. +To update a domain’s name servers and/or IP addresses, +in the registrar, go to the domain in Domains, +then click the "Manage domain" button. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/logentry_description.html b/src/registrar/templates/django/admin/includes/descriptions/logentry_description.html new file mode 100644 index 000000000..0dc3fe94e --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/logentry_description.html @@ -0,0 +1,7 @@ ++Log entries represent instances where something was created, updated, or deleted within the registrar or /admin. +The table on this page is useful for searching actions across all records. +To understand what happened to an individual record (like a domain request), +it’s better to go to that specific page +(Domain requests) and click on the “History” button. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/public_contact_description.html b/src/registrar/templates/django/admin/includes/descriptions/public_contact_description.html new file mode 100644 index 000000000..809b62a33 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/public_contact_description.html @@ -0,0 +1,18 @@ ++Public contacts represent the three registry contact types (administrative, technical, and security) +and their fields that are exposed in WHOIS data. +
+ ++We don’t currently allow registrants to publish real contact information to WHOIS, +but we must publish something to WHOIS. For each of the contact types, we use default values that are +associated with the program instead of the real contact information, +which we then redact in whole at the registry/WHOIS. +We do allow registrants to set a security contact email address, +which is published to WHOIS when a user sets one. +
+ ++The public contacts in this table are a reflection of the data in the registry and should not be updated. +This information is primarily used by developers for validation purposes. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/transition_domain_description.html b/src/registrar/templates/django/admin/includes/descriptions/transition_domain_description.html new file mode 100644 index 000000000..331c7b18b --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/transition_domain_description.html @@ -0,0 +1,4 @@ ++This table represents the domains that were transitioned from the old registry in November 2023. +This data has been preserved for historical reference and should not be updated. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/user_description.html b/src/registrar/templates/django/admin/includes/descriptions/user_description.html new file mode 100644 index 000000000..2f1777169 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/user_description.html @@ -0,0 +1,16 @@ ++A user is anyone who has access to the registrar. This includes request creators, domain managers, and CISA administrators. +Within each user record, you can review that user’s permissions and user status. +
+ ++If a user has a domain request in ineligible status, then their user status will be “restricted.” +Users who are in restricted status cannot create/edit domain requests or approved domains, +and their existing requests are locked. They will see a 403 error if they try to take action in the registrar. +
+ ++Each user record displays the associated “contact” info for that user, +which is the same info found in the Contacts table. +Updating these details on the user record will also update the corresponding contact record for that user. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/user_domain_role_description.html b/src/registrar/templates/django/admin/includes/descriptions/user_domain_role_description.html new file mode 100644 index 000000000..7066fcb93 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/user_domain_role_description.html @@ -0,0 +1,10 @@ ++This table represents the managers who are assigned to each domain in the registrar. +There are separate records for each domain/manager combination. +Managers can update information related to a domain, such as DNS data and security contact. +
+ ++The creator of an approved domain request automatically becomes a manager for that domain. +Anyone who retrieves a domain invitation is also assigned the manager role. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/user_group_description.html b/src/registrar/templates/django/admin/includes/descriptions/user_group_description.html new file mode 100644 index 000000000..610c8b430 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/user_group_description.html @@ -0,0 +1,10 @@ ++Groups are a way to bundle admin permissions so they can be easily assigned to multiple users. +Once a group is created, it can be assigned to people via the Users table. +
+ ++To maintain a single source of truth across all environments (stable, staging, etc.), +the groups and permissions are set and updated through the codebase. +Do not add, edit or delete user groups here. +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/verified_by_staff_description.html b/src/registrar/templates/django/admin/includes/descriptions/verified_by_staff_description.html new file mode 100644 index 000000000..f7e4a58c9 --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/verified_by_staff_description.html @@ -0,0 +1,10 @@ ++This table contains users who have been allowed to bypass identity proofing through Login.gov after approval by a CISA representative. +Bypassing identity proofing means they will not be asked to provide a form of ID, PII, and so on. +
+ ++Additions to this table should be rare, and only after obtaining confirmation of their identity directly (or from a trusted person). +Once a verified-by-staff user has been added as a domain manager, they can be removed from this list, +(However, if they are removed as a domain manager for all domains and they attempt to sign in again, they will be identity proofed by Login.gov). +
diff --git a/src/registrar/templates/django/admin/includes/descriptions/website_description.html b/src/registrar/templates/django/admin/includes/descriptions/website_description.html new file mode 100644 index 000000000..f6f5bdd1c --- /dev/null +++ b/src/registrar/templates/django/admin/includes/descriptions/website_description.html @@ -0,0 +1,8 @@ ++This table lists all the “current websites” and “alternative domains” that users have submitted in domain requests since January 2024. +
+ ++This does not include any “requested domains” that have appeared within the Domain requests table. +Those names are managed in the Draft domains table. +
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py index 59aea4a0c..27825b9ea 100644 --- a/src/registrar/tests/test_admin.py +++ b/src/registrar/tests/test_admin.py @@ -21,6 +21,12 @@ from registrar.admin import ( MyHostAdmin, UserDomainRoleAdmin, VerifiedByStaffAdmin, + WebsiteAdmin, + DraftDomainAdmin, + FederalAgencyAdmin, + PublicContactAdmin, + TransitionDomainAdmin, + UserGroupAdmin, ) from registrar.models import ( Domain, @@ -33,6 +39,9 @@ from registrar.models import ( PublicContact, Host, Website, + FederalAgency, + UserGroup, + TransitionDomain, ) from registrar.models.user_domain_role import UserDomainRole from registrar.models.verified_by_staff import VerifiedByStaff @@ -95,6 +104,23 @@ class TestDomainAdmin(MockEppLib, WebTest): ) super().setUp() + @less_console_noise_decorator + def test_has_model_description(self): + """Tests if this model has a model description on the table view""" + p = "adminpass" + self.client.login(username="superuser", password=p) + response = self.client.get( + "/admin/registrar/domain/", + follow=True, + ) + + # Make sure that the page is loaded correctly + self.assertEqual(response.status_code, 200) + + # Test for a description snippet + self.assertContains(response, "This table contains all approved domains in the .gov registrar.") + self.assertContains(response, "Show more") + @less_console_noise_decorator def test_contact_fields_on_domain_change_form_have_detail_table(self): """Tests if the contact fields in the inlined Domain information have the detail table @@ -511,7 +537,7 @@ class TestDomainAdmin(MockEppLib, WebTest): # There are 4 template references to Federal (4) plus four references in the table # for our actual domain_request - self.assertContains(response, "Federal", count=36) + self.assertContains(response, "Federal", count=42) # This may be a bit more robust self.assertContains(response, '