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;
background-color: var(--body-bg);
.dja-details-summary { .dja-details-summary {
color: var(--header-link-color); cursor: pointer;
background-color: var(--primary); color: var(--body-quiet-color);
} }
.dja-details-contents {
tr { @media (max-width: 1024px){
background-color: var(--darkened-bg); .dja-detail-contents {
max-width: 400px !important;
overflow-x: scroll !important;
} }
} }
}
table.dja-user-detail-table {
margin-left: 160px;
tr { tr {
background-color: var(--body-bg); background-color: transparent;
}
}
.admin-icon-group {
position: relative;
display: flex;
align-items: center;
.usa-button__icon {
position: absolute;
right: 0;
height: 100%;
} }
input { td, th {
// Allow for padding around the copy button padding-left: 12px;
padding-right: 35px !important; border: none
// Match the height of other inputs }
min-height: 2.25rem !important;
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,35 +20,36 @@ 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%}
{% endif %} {% endif %}
{% 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>
</div> </div>
{% 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,72 +5,102 @@
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" %}
<div class="readonly"> {% if all_contacts.count > 2 %}
{% for contact in field.contents|split:", " %} <div class="readonly">
<a href="#" class="other-contact__{{forloop.counter}}">{{ contact }}</a>{% if not forloop.last %}, {% endif %} {% for contact in all_contacts %}
{% endfor %} <a href="{% url 'admin:registrar_contact_change' contact.id %}">{{ contact.get_formatted_name }}</a>{% if not forloop.last %}, {% endif %}
</div> {% endfor %}
</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.
It is not useful to be redirected to the object definition, It is not useful to be redirected to the object definition,
rather it is more useful in this scenario to be redirected to the rather it is more useful in this scenario to be redirected to the
actual website (as its just a plaintext string otherwise). actual website (as its just a plaintext string otherwise).
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">
<a href="{{ website }}" class="padding-top-1 current-website__{{forloop.counter}}">{{ website }}</a>{% if not forloop.last %}, {% endif %} {% with total_websites=field.contents|split:", " %}
{% endfor %} {% for website in total_websites %}
<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 %}
{% 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>
<table> <summary class="padding-1 padding-left-0 dja-details-summary">Details</summary>
<tbody> <div class="grid-container margin-left-0 padding-left-0 padding-right-0 dja-details-contents">
{% for contact in original.other_contacts.all %} <table>
{% comment %} <thead>
Since we can't get the id from field, we can embed this information here. <tr>
Then we can link these two fields using javascript. <th colspan="4">Other contact information</th>
{% endcomment %} <tr>
<tr data-contact-id="{{ contact.id }}" data-contact-url="{% url 'admin:registrar_contact_change' contact.id %}"> </thead>
<th scope="row">{{contact.first_name}} {{contact.last_name}}</th> <tbody>
<td>{{ contact.title }}</td> {% for contact in all_contacts %}
<td>{{ contact.email }}</td> <tr>
<td>{{ contact.phone }}</td> <th class="padding-left-1" scope="row">{{ contact.get_formatted_name }}</th>
{# Copy button for the email #} <td class="padding-left-1">{{ contact.title }}</td>
<td class="font-size-sm"> <td class="padding-left-1">{{ contact.email }}</td>
<input class="dja-clipboard-input" type="hidden" value="{{ contact.email }}"> <td class="padding-left-1">{{ contact.phone }}</td>
<button </tr>
class="usa-button usa-button--unstyled usa-button__icon usa-button__clipboard text-no-underline" {% endfor %}
type="button" </tbody>
> </table>
<svg </div>
class="usa-icon" </details>
> {% endif %}
<use aria-hidden="true" xlink:href="{%static 'img/sprite.svg'%}#content_copy"></use> {% endwith %}
</svg>
Copy email
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</details>
{% endif %} {% 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)