Merge branch 'za/1852-user-contact-info-inline' into za/1848-copy-contact-email-to-clipboard

This commit is contained in:
zandercymatics 2024-03-28 12:06:54 -06:00
commit bcb1f80f57
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
12 changed files with 287 additions and 231 deletions

View file

@ -925,6 +925,9 @@ class DomainInformationAdmin(ListHeaderAdmin):
), ),
] ]
# Readonly fields for analysts and superusers
readonly_fields = ("other_contacts",)
# Read only that we'll leverage for CISA Analysts # Read only that we'll leverage for CISA Analysts
analyst_readonly_fields = [ analyst_readonly_fields = [
"creator", "creator",
@ -936,7 +939,6 @@ class DomainInformationAdmin(ListHeaderAdmin):
"no_other_contacts_rationale", "no_other_contacts_rationale",
"anything_else", "anything_else",
"is_policy_acknowledged", "is_policy_acknowledged",
"other_contacts",
] ]
# For each filter_horizontal, init in admin js extendFilterHorizontalWidgets # For each filter_horizontal, init in admin js extendFilterHorizontalWidgets
@ -1135,6 +1137,9 @@ class DomainRequestAdmin(ListHeaderAdmin):
), ),
] ]
# Readonly fields for analysts and superusers
readonly_fields = ("other_contacts", "current_websites", "alternative_domains")
# Read only that we'll leverage for CISA Analysts # Read only that we'll leverage for CISA Analysts
analyst_readonly_fields = [ analyst_readonly_fields = [
"creator", "creator",
@ -1142,8 +1147,6 @@ class DomainRequestAdmin(ListHeaderAdmin):
"requested_domain", "requested_domain",
"approved_domain", "approved_domain",
"alternative_domains", "alternative_domains",
"other_contacts",
"current_websites",
"purpose", "purpose",
"submitter", "submitter",
"no_other_contacts_rationale", "no_other_contacts_rationale",
@ -1319,7 +1322,7 @@ class DomainRequestAdmin(ListHeaderAdmin):
readonly_fields.extend([field.name for field in self.model._meta.fields]) readonly_fields.extend([field.name for field in self.model._meta.fields])
# Add the multi-select fields to readonly_fields: # Add the multi-select fields to readonly_fields:
# Complex fields like ManyToManyField require special handling # Complex fields like ManyToManyField require special handling
readonly_fields.extend(["current_websites", "other_contacts", "alternative_domains"]) readonly_fields.extend(["alternative_domains"])
if request.user.has_perm("registrar.full_access_permission"): if request.user.has_perm("registrar.full_access_permission"):
return readonly_fields return readonly_fields
@ -1432,7 +1435,6 @@ class DomainAdmin(ListHeaderAdmin):
) )
def queryset(self, request, queryset): def queryset(self, request, queryset):
logger.debug(self.value())
if self.value() == "1": if self.value() == "1":
return queryset.filter(domain_info__is_election_board=True) return queryset.filter(domain_info__is_election_board=True)
if self.value() == "0": if self.value() == "0":

View file

@ -230,32 +230,6 @@ function checkToListThenInitWidget(toListId, attempts) {
} }
} }
(function() {
function addUrlsToOtherContacts() {
document.addEventListener('DOMContentLoaded', function() {
// Select all table rows that have a data-contact-id attribute
let contactRows = document.querySelectorAll("tr[data-contact-url]");
if (contactRows){
// Add a click event listener to each row
let index = 1;
contactRows.forEach(function(row) {
let otherContactUrl = row.getAttribute("data-contact-url");
if (otherContactUrl){
let otherContact = document.querySelector(`.other-contact__${index}`);
if (otherContact) {
otherContact.href = otherContactUrl;
}
}
index++;
});
}
});
}
addUrlsToOtherContacts()
})();
// Initialize the widget: // Initialize the widget:
// add related buttons to the widget for edit, delete and view // add related buttons to the widget for edit, delete and view
// add event listeners on the from list, the to list, and selector buttons which either enable or disable the related buttons // add event listeners on the from list, the to list, and selector buttons which either enable or disable the related buttons

View file

@ -61,7 +61,6 @@
function createComparativeColumnChart(canvasId, title, labelOne, labelTwo) { function createComparativeColumnChart(canvasId, title, labelOne, labelTwo) {
var canvas = document.getElementById(canvasId); var canvas = document.getElementById(canvasId);
if (!canvas) { if (!canvas) {
console.log("Could not find canvas")
return return
} }

View file

@ -347,83 +347,103 @@ input.admin-confirm-button {
color: $dhs-blue-70; color: $dhs-blue-70;
} }
.admin-icon-group {
position: relative;
display: flex;
align-items: center;
.usa-button__icon {
position: absolute;
right: 0;
height: 100%;
}
input {
// Allow for padding around the copy button
padding-right: 35px !important;
// Match the height of other inputs
min-height: 2.25rem !important;
}
}
td.font-size-sm {
button.usa-button__icon {
font-size: 16px;
}
}
details.dja-detail-table { details.dja-detail-table {
background-color: var(--darkened-bg);
display: inline-table; display: inline-table;
.dja-details-summary {
color: var(--header-link-color);
background-color: var(--primary);
}
.dja-details-contents {
tr {
background-color: var(--darkened-bg);
}
}
}
table.dja-user-detail-table {
margin-left: 160px;
tr {
background-color: var(--body-bg); background-color: var(--body-bg);
} .dja-details-summary {
} cursor: pointer;
color: var(--body-quiet-color);
.admin-icon-group {
position: relative;
display: flex;
align-items: center;
.usa-button__icon {
position: absolute;
right: 0;
height: 100%;
} }
input { @media (max-width: 1024px){
// Allow for padding around the copy button .dja-detail-contents {
padding-right: 35px !important; max-width: 400px !important;
// Match the height of other inputs overflow-x: scroll !important;
min-height: 2.25rem !important; }
}
tr {
background-color: transparent;
}
td, th {
padding-left: 12px;
border: none
}
thead > tr > th {
border-radius: 4px;
border-top: none;
border-bottom: none;
} }
} }
td.font-size-sm {
button.usa-button__icon { address.margin-top-neg-1__detail-list {
font-size: 16px; margin-top: -8px !important;
}
.dja-detail-list {
dl {
padding-left: 0px !important;
margin-top: 5px !important;
}
// Mimic the normal label size
dt {
font-size: 0.8125rem;
color: var(--body-quiet-color);
}
address {
font-size: 0.8125rem;
color: var(--body-quiet-color);
} }
} }
.no-outline-on-click:focus { address.dja-address-contact-list {
outline: none !important; font-size: 0.8125rem;
color: var(--body-quiet-color);
}
// Mimic the normal label size
@media (max-width: 1024px){
.dja-detail-list dt {
font-size: 0.875rem;
color: var(--body-quiet-color);
}
.dja-detail-list address {
font-size: 0.875rem;
color: var(--body-quiet-color);
}
} }
.errors span.select2-selection { .errors span.select2-selection {
border: 1px solid var(--error-fg) !important; border: 1px solid var(--error-fg) !important;
} }
.admin-icon-group {
position: relative;
display: flex;
align-items: center;
.usa-button__icon {
position: absolute;
right: 0;
height: 100%;
}
input {
// Allow for padding around the copy button
padding-right: 35px !important;
// Match the height of other inputs
min-height: 2.25rem !important;
}
}
td.font-size-sm {
button.usa-button__icon {
font-size: 16px;
}
}

View file

@ -6,15 +6,11 @@ It is not inherently customizable on its own, so we can modify this instead.
https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/includes/fieldset.html https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/includes/fieldset.html
{% endcomment %} {% endcomment %}
<fieldset class="module aligned {{ fieldset.classes }}"> <fieldset class="module aligned {{ fieldset.classes }}">
{% block fieldset_title %}
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %} {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
{% endblock fieldset_title %}
{% block fieldset_description %}
{% if fieldset.description %} {% if fieldset.description %}
<div class="description">{{ fieldset.description|safe }}</div> <div class="description">{{ fieldset.description|safe }}</div>
{% endif %} {% endif %}
{% endblock fieldset_description %}
{% for line in fieldset %} {% for line in fieldset %}
<div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}"> <div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
@ -24,16 +20,19 @@ https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/
{% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %} {% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
<div class="flex-container{% if not line.fields|length == 1 %} fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}{% elif field.is_checkbox %} checkbox-row{% endif %}"> <div class="flex-container{% if not line.fields|length == 1 %} fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}{% elif field.is_checkbox %} checkbox-row{% endif %}">
{% if field.is_checkbox %} {% if field.is_checkbox %}
{# .gov override #}
{% block field_checkbox %} {% block field_checkbox %}
{{ field.field }}{{ field.label_tag }} {{ field.field }}{{ field.label_tag }}
{% endblock field_checkbox%} {% endblock field_checkbox%}
{% else %} {% else %}
{{ field.label_tag }} {{ field.label_tag }}
{% if field.is_readonly %} {% if field.is_readonly %}
{# .gov override #}
{% block field_readonly %} {% block field_readonly %}
<div class="readonly">{{ field.contents }}</div> <div class="readonly">{{ field.contents }}</div>
{% endblock field_readonly%} {% endblock field_readonly%}
{% else %} {% else %}
{# .gov override #}
{% block field_other %} {% block field_other %}
{{ field.field }} {{ field.field }}
{% endblock field_other%} {% endblock field_other%}
@ -41,11 +40,8 @@ https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/
{% endif %} {% endif %}
</div> </div>
{% block before_help_text %}
{# For templating purposes #}
{% endblock before_help_text %}
{% if field.field.help_text %} {% if field.field.help_text %}
{# .gov override #}
{% block help_text %} {% block help_text %}
<div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}> <div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}>
<div>{{ field.field.help_text|safe }}</div> <div>{{ field.field.help_text|safe }}</div>
@ -53,6 +49,7 @@ https://github.com/django/django/blob/main/django/contrib/admin/templates/admin/
{% endblock help_text %} {% endblock help_text %}
{% endif %} {% endif %}
{# .gov addition #}
{% block after_help_text %} {% block after_help_text %}
{# For templating purposes #} {# For templating purposes #}
{% endblock after_help_text %} {% endblock after_help_text %}

View file

@ -3,6 +3,13 @@
{% block field_sets %} {% block field_sets %}
{% for fieldset in adminform %} {% for fieldset in adminform %}
{% comment %}
TODO: this will eventually need to be changed to something like this
if we ever want to customize this file:
{% include "django/admin/includes/domain_information_fieldset.html" %} {% include "django/admin/includes/domain_information_fieldset.html" %}
Use detail_table_fieldset as an example, or just extend it.
{% endcomment %}
{% include "django/admin/includes/detail_table_fieldset.html" %}
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

View file

@ -4,8 +4,16 @@
{% block field_sets %} {% block field_sets %}
{# Create an invisible <a> tag so that we can use a click event to toggle the modal. #} {# Create an invisible <a> tag so that we can use a click event to toggle the modal. #}
<a id="invisible-ineligible-modal-toggler" class="display-none" href="#toggle-set-ineligible" aria-controls="toggle-set-ineligible" data-open-modal></a> <a id="invisible-ineligible-modal-toggler" class="display-none" href="#toggle-set-ineligible" aria-controls="toggle-set-ineligible" data-open-modal></a>
{% for fieldset in adminform %} {% for fieldset in adminform %}
{% include "django/admin/includes/domain_request_fieldset.html" %} {% comment %}
TODO: this will eventually need to be changed to something like this
if we ever want to customize this file:
{% include "django/admin/includes/domain_information_fieldset.html" %}
Use detail_table_fieldset as an example, or just extend it.
{% endcomment %}
{% include "django/admin/includes/detail_table_fieldset.html" %}
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

View file

@ -0,0 +1,51 @@
{% load i18n static %}
<address class="{% if no_title_top_padding %}margin-top-neg-1__detail-list{% endif %} dja-address-contact-list">
{% if show_formatted_name %}
{% if contact.get_formatted_name %}
<a href="{% url 'admin:registrar_contact_change' user.id %}">{{ user.get_formatted_name }}</a><br />
{% else %}
None<br />
{% endif %}
{% endif %}
{% if user.title or user.contact.title or user.email or user.contact.email or user.phone or user.contact.phone %}
{# Title #}
{% if user.title or user.contact.title %}
{% if user.contact.title %}
{{ user.contact.title }}
{% else %}
{{ user.title }}
{% endif %}
<br>
{% else %}
None<br>
{% endif %}
{# Email #}
{% if user.email or user.contact.email %}
{% if user.contact.email %}
{{ user.contact.email }}
{% else %}
{{ user.email }}
{% endif %}
<br>
{% else %}
None<br>
{% endif %}
{# Phone #}
{% if user.phone or user.contact.phone %}
{% if user.contact.phone %}
{{ user.contact.phone }}
{% else %}
{{ user.phone }}
{% endif %}
<br>
{% else %}
None<br>
{% endif %}
{% else %}
No additional contact information found.
{% endif %}
</address>

View file

@ -5,12 +5,28 @@
This is using a custom implementation fieldset.html (see admin/fieldset.html) This is using a custom implementation fieldset.html (see admin/fieldset.html)
{% endcomment %} {% endcomment %}
{% block field_readonly %} {% block field_readonly %}
{% with all_contacts=original.other_contacts.all %}
{% if field.field.name == "other_contacts" %} {% if field.field.name == "other_contacts" %}
{% if all_contacts.count > 2 %}
<div class="readonly"> <div class="readonly">
{% for contact in field.contents|split:", " %} {% for contact in all_contacts %}
<a href="#" class="other-contact__{{forloop.counter}}">{{ contact }}</a>{% if not forloop.last %}, {% endif %} <a href="{% url 'admin:registrar_contact_change' contact.id %}">{{ contact.get_formatted_name }}</a>{% if not forloop.last %}, {% endif %}
{% endfor %} {% endfor %}
</div> </div>
{% else %}
<div class="flex-container dja-detail-list">
<dl class="usa-list usa-list--unstyled margin-0">
{% for contact in all_contacts %}
<dt class="{% if forloop.counter == 1%}margin-top-0{% endif %}">
Organization contact {{forloop.counter}}
</dt>
<dd>
{% include "django/admin/includes/contact_detail_list.html" with user=contact show_formatted_name=True %}
</dd>
{% endfor %}
</dl>
</div>
{% endif %}
{% elif field.field.name == "current_websites" %} {% elif field.field.name == "current_websites" %}
{% comment %} {% comment %}
The "website" model is essentially just a text field. The "website" model is essentially just a text field.
@ -20,52 +36,64 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
This ONLY applies to analysts. For superusers, its business as usual. This ONLY applies to analysts. For superusers, its business as usual.
{% endcomment %} {% endcomment %}
{% for website in field.contents|split:", " %} <div class="readonly">
{% with total_websites=field.contents|split:", " %}
{% for website in total_websites %}
<a href="{{ website }}" class="padding-top-1 current-website__{{forloop.counter}}">{{ website }}</a>{% if not forloop.last %}, {% endif %} <a href="{{ website }}" class="padding-top-1 current-website__{{forloop.counter}}">{{ website }}</a>{% if not forloop.last %}, {% endif %}
{# Acts as a <br> #}
{% if total_websites|length < 5 %}
<div class="display-block margin-top-1"></div>
{% endif %}
{% endfor %} {% endfor %}
{% endwith %}
</div>
{% elif field.field.name == "alternative_domains" %}
<div class="readonly">
{% for alt_domain in original.alternative_domains.all %}
<a href="{% url 'admin:registrar_website_change' alt_domain.id %}">{{ alt_domain }}</a>{% if not forloop.last %}, {% endif %}
{% endfor %}
</div>
{% else %} {% else %}
<div class="readonly">{{ field.contents }}</div> <div class="readonly">{{ field.contents }}</div>
{% endif %} {% endif %}
{% endwith %}
{% endblock field_readonly %} {% endblock field_readonly %}
{% block after_help_text %} {% block after_help_text %}
{% if field.field.name == "creator" %} {% if field.field.name == "creator" %}
{% include "django/admin/includes/contact_detail_table.html" with user=original.creator field_name="creator" %} <div class="flex-container">
<label aria-label="Creator contact details"></label>
{% include "django/admin/includes/contact_detail_list.html" with user=original.creator no_title_top_padding=field.is_readonly %}
</div>
{% elif field.field.name == "submitter" %} {% elif field.field.name == "submitter" %}
{% include "django/admin/includes/contact_detail_table.html" with user=original.submitter field_name="submitter" %} <div class="flex-container">
<label aria-label="Submitter contact details"></label>
{% include "django/admin/includes/contact_detail_list.html" with user=original.submitter no_title_top_padding=field.is_readonly %}
</div>
{% elif field.field.name == "authorizing_official" %} {% elif field.field.name == "authorizing_official" %}
{% include "django/admin/includes/contact_detail_table.html" with user=original.authorizing_official field_name="authorizing_official" %} <div class="flex-container">
<label aria-label="Authorizing official contact details"></label>
{% include "django/admin/includes/contact_detail_list.html" with user=original.authorizing_official no_title_top_padding=field.is_readonly %}
</div>
{% elif field.field.name == "other_contacts" and original.other_contacts.all %} {% elif field.field.name == "other_contacts" and original.other_contacts.all %}
<details class="margin-top-1 dja-detail-table"> {% with all_contacts=original.other_contacts.all %}
<summary class="padding-1 dja-details-summary">Details</summary> {% if all_contacts.count > 2 %}
<div class="grid-container padding-left-0 padding-right-0 dja-details-contents"> <details class="margin-top-1 dja-detail-table" aria-role="button" open>
<summary class="padding-1 padding-left-0 dja-details-summary">Details</summary>
<div class="grid-container margin-left-0 padding-left-0 padding-right-0 dja-details-contents">
<table> <table>
<thead>
<tr>
<th colspan="4">Other contact information</th>
<tr>
</thead>
<tbody> <tbody>
{% for contact in original.other_contacts.all %} {% for contact in all_contacts %}
{% comment %} <tr>
Since we can't get the id from field, we can embed this information here. <th class="padding-left-1" scope="row">{{ contact.get_formatted_name }}</th>
Then we can link these two fields using javascript. <td class="padding-left-1">{{ contact.title }}</td>
{% endcomment %} <td class="padding-left-1">{{ contact.email }}</td>
<tr data-contact-id="{{ contact.id }}" data-contact-url="{% url 'admin:registrar_contact_change' contact.id %}"> <td class="padding-left-1">{{ contact.phone }}</td>
<th scope="row">{{contact.first_name}} {{contact.last_name}}</th>
<td>{{ contact.title }}</td>
<td>{{ contact.email }}</td>
<td>{{ contact.phone }}</td>
{# Copy button for the email #}
<td class="font-size-sm">
<input class="dja-clipboard-input" type="hidden" value="{{ contact.email }}">
<button
class="usa-button usa-button--unstyled usa-button__icon usa-button__clipboard text-no-underline"
type="button"
>
<svg
class="usa-icon"
>
<use aria-hidden="true" xlink:href="{%static 'img/sprite.svg'%}#content_copy"></use>
</svg>
Copy email
</button>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
@ -73,4 +101,6 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
</div> </div>
</details> </details>
{% endif %} {% endif %}
{% endwith %}
{% endif %}
{% endblock after_help_text %} {% endblock after_help_text %}

View file

@ -1,2 +0,0 @@
{% extends "django/admin/includes/detail_table_fieldset.html" %}
{# Stubbed file for future expansion #}

View file

@ -1,2 +0,0 @@
{% extends "django/admin/includes/detail_table_fieldset.html" %}
{# Stubbed file for future expansion #}

View file

@ -1300,17 +1300,13 @@ class TestDomainRequestAdmin(MockEppLib):
# == Check for the creator == # # == Check for the creator == #
# Check for the right title, email, and phone number in the response. # Check for the right title, email, and phone number in the response.
# We only need to check for the end tag
# (Otherwise this test will fail if we change classes, etc)
expected_email = "meoward.jones@igorville.gov" expected_email = "meoward.jones@igorville.gov"
expected_creator_fields = [ expected_creator_fields = [
# Field, expected value # Field, expected value
("title", "Treat inspector</td>"), ("title", "Treat inspector"),
("email", f"{expected_email}</td>"), ("email", "meoward.jones@igorville.gov"),
# Check for the existence of the copy button input. ("phone", "(555) 123 12345"),
# Lets keep things simple to minimize future conflicts.
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 123 12345</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_creator_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_creator_fields)
@ -1321,10 +1317,10 @@ class TestDomainRequestAdmin(MockEppLib):
expected_email = "mayor@igorville.gov" expected_email = "mayor@igorville.gov"
expected_submitter_fields = [ expected_submitter_fields = [
# Field, expected value # Field, expected value
("title", "Admin Tester</td>"), ("title", "Admin Tester"),
("email", f"{expected_email}</td>"), ("email", "mayor@igorville.gov"),
("phone", "(555) 555 5556"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 555 5556</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_submitter_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_submitter_fields)
self.assertContains(response, "Testy2 Tester2") self.assertContains(response, "Testy2 Tester2")
@ -1334,42 +1330,27 @@ class TestDomainRequestAdmin(MockEppLib):
expected_ao_fields = [ expected_ao_fields = [
# Field, expected value # Field, expected value
("title", "Chief Tester</td>"), ("title", "Chief Tester</td>"),
("email", f"{expected_email}</td>"), ("email", "testy@town.com</td>"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 555 5555</td>"), ("phone", "(555) 555 5555</td>"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_ao_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_ao_fields)
# count=4 because the underlying domain has two users with this name. # count=5 because the underlying domain has two users with this name.
# The dropdown has 3 of these. # The dropdown has 3 of these.
self.assertContains(response, "Testy Tester", count=4) self.assertContains(response, "Testy Tester", count=5)
# Check for table titles. We only need to check for the end tag
# (Otherwise this test will fail if we change classes, etc)
# Title. Count=3 because this table appears on three records.
self.assertContains(response, "Title</th>", count=3)
# Email. Count=3 because this table appears on three records.
self.assertContains(response, "Email</th>", count=3)
# Phone. Count=3 because this table appears on three records.
self.assertContains(response, "Phone</th>", count=3)
# == Test the other_employees field == # # == Test the other_employees field == #
expected_email = "testy@town.com" expected_email = "testy@town.com"
expected_other_employees_fields = [ expected_other_employees_fields = [
# Field, expected value # Field, expected value
("title", "Another Tester</td>"), ("title", "Another Tester"),
("email", f"{expected_email}</td>"), ("email", "testy2@town.com"),
("phone", "(555) 555 5557"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 555 5557</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields)
# count=1 as only one should exist in a table
self.assertContains(response, "Testy Tester</th>", count=1)
def test_save_model_sets_restricted_status_on_user(self): def test_save_model_sets_restricted_status_on_user(self):
with less_console_noise(): with less_console_noise():
# make sure there is no user with this email # make sure there is no user with this email
@ -1453,6 +1434,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.assertContains(response, "Yes, select ineligible status") self.assertContains(response, "Yes, select ineligible status")
def test_readonly_when_restricted_creator(self): def test_readonly_when_restricted_creator(self):
self.maxDiff = None
with less_console_noise(): with less_console_noise():
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW) domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
with boto3_mocking.clients.handler_for("sesv2", self.mock_client): with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
@ -1465,6 +1447,9 @@ class TestDomainRequestAdmin(MockEppLib):
readonly_fields = self.admin.get_readonly_fields(request, domain_request) readonly_fields = self.admin.get_readonly_fields(request, domain_request)
expected_fields = [ expected_fields = [
"other_contacts",
"current_websites",
"alternative_domains",
"id", "id",
"created_at", "created_at",
"updated_at", "updated_at",
@ -1497,8 +1482,6 @@ class TestDomainRequestAdmin(MockEppLib):
"is_policy_acknowledged", "is_policy_acknowledged",
"submission_date", "submission_date",
"notes", "notes",
"current_websites",
"other_contacts",
"alternative_domains", "alternative_domains",
] ]
@ -1512,13 +1495,14 @@ class TestDomainRequestAdmin(MockEppLib):
readonly_fields = self.admin.get_readonly_fields(request) readonly_fields = self.admin.get_readonly_fields(request)
expected_fields = [ expected_fields = [
"other_contacts",
"current_websites",
"alternative_domains",
"creator", "creator",
"about_your_organization", "about_your_organization",
"requested_domain", "requested_domain",
"approved_domain", "approved_domain",
"alternative_domains", "alternative_domains",
"other_contacts",
"current_websites",
"purpose", "purpose",
"submitter", "submitter",
"no_other_contacts_rationale", "no_other_contacts_rationale",
@ -1535,7 +1519,11 @@ class TestDomainRequestAdmin(MockEppLib):
readonly_fields = self.admin.get_readonly_fields(request) readonly_fields = self.admin.get_readonly_fields(request)
expected_fields = [] expected_fields = [
"other_contacts",
"current_websites",
"alternative_domains",
]
self.assertEqual(readonly_fields, expected_fields) self.assertEqual(readonly_fields, expected_fields)
@ -1979,6 +1967,7 @@ class TestDomainInformationAdmin(TestCase):
p = "userpass" p = "userpass"
self.client.login(username="staffuser", password=p) self.client.login(username="staffuser", password=p)
response = self.client.get( response = self.client.get(
"/admin/registrar/domaininformation/{}/change/".format(domain_info.pk), "/admin/registrar/domaininformation/{}/change/".format(domain_info.pk),
follow=True, follow=True,
@ -2043,12 +2032,10 @@ class TestDomainInformationAdmin(TestCase):
expected_email = "meoward.jones@igorville.gov" expected_email = "meoward.jones@igorville.gov"
expected_creator_fields = [ expected_creator_fields = [
# Field, expected value # Field, expected value
("title", "Treat inspector</td>"), ("title", "Treat inspector"),
("email", f"{expected_email}</td>"), ("email", "meoward.jones@igorville.gov"),
# Check for the existence of the copy button input. ("phone", "(555) 123 12345"),
# Lets keep things simple to minimize future conflicts.
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 123 12345</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_creator_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_creator_fields)
@ -2059,10 +2046,10 @@ class TestDomainInformationAdmin(TestCase):
expected_email = "mayor@igorville.gov" expected_email = "mayor@igorville.gov"
expected_submitter_fields = [ expected_submitter_fields = [
# Field, expected value # Field, expected value
("title", "Admin Tester</td>"), ("title", "Admin Tester"),
("email", f"{expected_email}</td>"), ("email", "mayor@igorville.gov"),
("phone", "(555) 555 5556"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 555 5556</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_submitter_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_submitter_fields)
self.assertContains(response, "Testy2 Tester2") self.assertContains(response, "Testy2 Tester2")
@ -2071,43 +2058,28 @@ class TestDomainInformationAdmin(TestCase):
expected_email = "testy@town.com" expected_email = "testy@town.com"
expected_ao_fields = [ expected_ao_fields = [
# Field, expected value # Field, expected value
("title", "Chief Tester</td>"), ("title", "Chief Tester"),
("email", "testy@town.com</td>"), ("email", "testy@town.com"),
("phone", "(555) 555 5555"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 555 5555</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_ao_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_ao_fields)
# count=4 because the underlying domain has two users with this name. # count=5 because the underlying domain has two users with this name.
# The dropdown has 3 of these. # The dropdown has 3 of these.
self.assertContains(response, "Testy Tester", count=4) self.assertContains(response, "Testy Tester", count=5)
# Check for table titles. We only need to check for the end tag
# (Otherwise this test will fail if we change classes, etc)
# Title. Count=3 because this table appears on three records.
self.assertContains(response, "Title</th>", count=3)
# Email. Count=3 because this table appears on three records.
self.assertContains(response, "Email</th>", count=3)
# Phone. Count=3 because this table appears on three records.
self.assertContains(response, "Phone</th>", count=3)
# == Test the other_employees field == # # == Test the other_employees field == #
expected_email = "testy@town.com" expected_email = "testy@town.com"
expected_other_employees_fields = [ expected_other_employees_fields = [
# Field, expected value # Field, expected value
("title", "Another Tester</td>"), ("title", "Another Tester"),
("email", f"{expected_email}</td>"), ("email", "testy2@town.com"),
("phone", "(555) 555 5557"),
("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'), ("email_copy_button_input", f'<input class="dja-clipboard-input" type="hidden" value="{expected_email}"'),
("phone", "(555) 555 5557</td>"),
] ]
self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields) self.test_helper.assert_response_contains_distinct_values(response, expected_other_employees_fields)
# count=1 as only one should exist in a table
self.assertContains(response, "Testy Tester</th>", count=1)
def test_readonly_fields_for_analyst(self): def test_readonly_fields_for_analyst(self):
"""Ensures that analysts have their permissions setup correctly""" """Ensures that analysts have their permissions setup correctly"""
with less_console_noise(): with less_console_noise():
@ -2117,6 +2089,7 @@ class TestDomainInformationAdmin(TestCase):
readonly_fields = self.admin.get_readonly_fields(request) readonly_fields = self.admin.get_readonly_fields(request)
expected_fields = [ expected_fields = [
"other_contacts",
"creator", "creator",
"type_of_work", "type_of_work",
"more_organization_information", "more_organization_information",
@ -2126,7 +2099,6 @@ class TestDomainInformationAdmin(TestCase):
"no_other_contacts_rationale", "no_other_contacts_rationale",
"anything_else", "anything_else",
"is_policy_acknowledged", "is_policy_acknowledged",
"other_contacts",
] ]
self.assertEqual(readonly_fields, expected_fields) self.assertEqual(readonly_fields, expected_fields)