diff --git a/.github/workflows/deploy-branch-to-sandbox.yaml b/.github/workflows/deploy-branch-to-sandbox.yaml
index f57961fa8..652aec207 100644
--- a/.github/workflows/deploy-branch-to-sandbox.yaml
+++ b/.github/workflows/deploy-branch-to-sandbox.yaml
@@ -29,6 +29,7 @@ on:
- hotgov
- litterbox
- ms
+ - ad
# GitHub Actions has no "good" way yet to dynamically input branches
branch:
description: 'Branch to deploy'
diff --git a/.github/workflows/deploy-sandbox.yaml b/.github/workflows/deploy-sandbox.yaml
index 57561919c..fe0a19089 100644
--- a/.github/workflows/deploy-sandbox.yaml
+++ b/.github/workflows/deploy-sandbox.yaml
@@ -29,6 +29,7 @@ jobs:
|| startsWith(github.head_ref, 'litterbox/')
|| startsWith(github.head_ref, 'ag/')
|| startsWith(github.head_ref, 'ms/')
+ || startsWith(github.head_ref, 'ad/')
outputs:
environment: ${{ steps.var.outputs.environment}}
runs-on: "ubuntu-latest"
diff --git a/.github/workflows/migrate.yaml b/.github/workflows/migrate.yaml
index 3ebee59f9..70ff8ee95 100644
--- a/.github/workflows/migrate.yaml
+++ b/.github/workflows/migrate.yaml
@@ -16,6 +16,7 @@ on:
- stable
- staging
- development
+ - ad
- ms
- ag
- litterbox
diff --git a/.github/workflows/reset-db.yaml b/.github/workflows/reset-db.yaml
index 49e4b5e5f..b6fa0fec5 100644
--- a/.github/workflows/reset-db.yaml
+++ b/.github/workflows/reset-db.yaml
@@ -16,6 +16,7 @@ on:
options:
- staging
- development
+ - ad
- ms
- ag
- litterbox
diff --git a/ops/manifests/manifest-ad.yaml b/ops/manifests/manifest-ad.yaml
new file mode 100644
index 000000000..73d6f96ff
--- /dev/null
+++ b/ops/manifests/manifest-ad.yaml
@@ -0,0 +1,32 @@
+---
+applications:
+- name: getgov-ad
+ buildpacks:
+ - python_buildpack
+ path: ../../src
+ instances: 1
+ memory: 512M
+ stack: cflinuxfs4
+ timeout: 180
+ command: ./run.sh
+ health-check-type: http
+ health-check-http-endpoint: /health
+ health-check-invocation-timeout: 40
+ env:
+ # Send stdout and stderr straight to the terminal without buffering
+ PYTHONUNBUFFERED: yup
+ # Tell Django where to find its configuration
+ DJANGO_SETTINGS_MODULE: registrar.config.settings
+ # Tell Django where it is being hosted
+ DJANGO_BASE_URL: https://getgov-ad.app.cloud.gov
+ # Tell Django how much stuff to log
+ DJANGO_LOG_LEVEL: INFO
+ # default public site location
+ GETGOV_PUBLIC_SITE_URL: https://get.gov
+ # Flag to disable/enable features in prod environments
+ IS_PRODUCTION: False
+ routes:
+ - route: getgov-ad.app.cloud.gov
+ services:
+ - getgov-credentials
+ - getgov-ad-database
diff --git a/src/package-lock.json b/src/package-lock.json
index 2ff464d5e..08e70dd51 100644
--- a/src/package-lock.json
+++ b/src/package-lock.json
@@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
- "@uswds/uswds": "^3.8.0",
+ "@uswds/uswds": "^3.8.1",
"pa11y-ci": "^3.0.1",
"sass": "^1.54.8"
},
@@ -187,9 +187,10 @@
}
},
"node_modules/@uswds/uswds": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.8.0.tgz",
- "integrity": "sha512-rMwCXe/u4HGkfskvS1Iuabapi/EXku3ChaIFW7y/dUhc7R1TXQhbbfp8YXEjmXPF0yqJnv9T08WPgS0fQqWZ8w==",
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.8.1.tgz",
+ "integrity": "sha512-bKG/B9mJF1v0yoqth48wQDzST5Xyu3OxxpePIPDyhKWS84oDrCehnu3Z88JhSjdIAJMl8dtjtH8YvdO9kZUpAg==",
+ "license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"classlist-polyfill": "1.2.0",
"object-assign": "4.1.1",
diff --git a/src/package.json b/src/package.json
index 58ae3a4ed..e16bc8198 100644
--- a/src/package.json
+++ b/src/package.json
@@ -10,11 +10,11 @@
"author": "",
"license": "ISC",
"dependencies": {
- "@uswds/uswds": "^3.8.0",
+ "@uswds/uswds": "^3.8.1",
"pa11y-ci": "^3.0.1",
"sass": "^1.54.8"
},
"devDependencies": {
"@uswds/compile": "^1.0.0-beta.3"
}
-}
\ No newline at end of file
+}
diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js
index d8bc21899..04f5417b0 100644
--- a/src/registrar/assets/js/get-gov-admin.js
+++ b/src/registrar/assets/js/get-gov-admin.js
@@ -207,15 +207,11 @@ function addOrRemoveSessionBoolean(name, add){
})();
+
/** An IIFE for pages in DjangoAdmin that use a clipboard button
*/
(function (){
- function copyInnerTextToClipboard(elem) {
- let text = elem.innerText
- navigator.clipboard.writeText(text)
- }
-
function copyToClipboardAndChangeIcon(button) {
// Assuming the input is the previous sibling of the button
let input = button.previousElementSibling;
@@ -224,7 +220,7 @@ function addOrRemoveSessionBoolean(name, add){
if (input) {
navigator.clipboard.writeText(input.value).then(function() {
// Change the icon to a checkmark on successful copy
- let buttonIcon = button.querySelector('.usa-button__clipboard use');
+ let buttonIcon = button.querySelector('.copy-to-clipboard use');
if (buttonIcon) {
let currentHref = buttonIcon.getAttribute('xlink:href');
let baseHref = currentHref.split('#')[0];
@@ -233,21 +229,17 @@ function addOrRemoveSessionBoolean(name, add){
buttonIcon.setAttribute('xlink:href', baseHref + '#check');
// Change the button text
- nearestSpan = button.querySelector("span")
+ let nearestSpan = button.querySelector("span")
+ let original_text = nearestSpan.innerText
nearestSpan.innerText = "Copied to clipboard"
setTimeout(function() {
// Change back to the copy icon
buttonIcon.setAttribute('xlink:href', currentHref);
- if (button.classList.contains('usa-button__small-text')) {
- nearestSpan.innerText = "Copy email";
- } else {
- nearestSpan.innerText = "Copy";
- }
+ nearestSpan.innerText = original_text;
}, 2000);
}
-
}).catch(function(error) {
console.error('Clipboard copy failed', error);
});
@@ -255,7 +247,7 @@ function addOrRemoveSessionBoolean(name, add){
}
function handleClipboardButtons() {
- clipboardButtons = document.querySelectorAll(".usa-button__clipboard")
+ clipboardButtons = document.querySelectorAll(".copy-to-clipboard")
clipboardButtons.forEach((button) => {
// Handle copying the text to your clipboard,
@@ -278,20 +270,7 @@ function addOrRemoveSessionBoolean(name, add){
});
}
- function handleClipboardLinks() {
- let emailButtons = document.querySelectorAll(".usa-button__clipboard-link");
- if (emailButtons){
- emailButtons.forEach((button) => {
- button.addEventListener("click", ()=>{
- copyInnerTextToClipboard(button);
- })
- });
- }
- }
-
handleClipboardButtons();
- handleClipboardLinks();
-
})();
@@ -605,3 +584,169 @@ function initializeWidgetOnList(list, parentId) {
}
}
})();
+
+
+/** An IIFE for copy summary button (appears in DomainRegistry models)
+*/
+(function (){
+ const copyButton = document.getElementById('id-copy-to-clipboard-summary');
+
+ if (copyButton) {
+ copyButton.addEventListener('click', function() {
+ /// Generate a rich HTML summary text and copy to clipboard
+
+ //------ Organization Type
+ const organizationTypeElement = document.getElementById('id_organization_type');
+ const organizationType = organizationTypeElement.options[organizationTypeElement.selectedIndex].text;
+
+ //------ Alternative Domains
+ const alternativeDomainsDiv = document.querySelector('.form-row.field-alternative_domains .readonly');
+ const alternativeDomainslinks = alternativeDomainsDiv.querySelectorAll('a');
+ const alternativeDomains = Array.from(alternativeDomainslinks).map(link => link.textContent);
+
+ //------ Existing Websites
+ const existingWebsitesDiv = document.querySelector('.form-row.field-current_websites .readonly');
+ const existingWebsiteslinks = existingWebsitesDiv.querySelectorAll('a');
+ const existingWebsites = Array.from(existingWebsiteslinks).map(link => link.textContent);
+
+ //------ Additional Contacts
+ // 1 - Create a hyperlinks map so we can display contact details and also link to the contact
+ const otherContactsDiv = document.querySelector('.form-row.field-other_contacts .readonly');
+ let otherContactLinks = [];
+ const nameToUrlMap = {};
+ if (otherContactsDiv) {
+ otherContactLinks = otherContactsDiv.querySelectorAll('a');
+ otherContactLinks.forEach(link => {
+ const name = link.textContent.trim();
+ const url = link.href;
+ nameToUrlMap[name] = url;
+ });
+ }
+
+ // 2 - Iterate through contact details and assemble html for summary
+ let otherContactsSummary = ""
+ const bulletList = document.createElement('ul');
+
+ // CASE 1 - Contacts are not in a table (this happens if there is only one or two other contacts)
+ const contacts = document.querySelectorAll('.field-other_contacts .dja-detail-list dd');
+ if (contacts) {
+ contacts.forEach(contact => {
+ // Check if the
element is not empty
+ const name = contact.querySelector('a#contact_info_name')?.innerText;
+ const title = contact.querySelector('span#contact_info_title')?.innerText;
+ const email = contact.querySelector('span#contact_info_email')?.innerText;
+ const phone = contact.querySelector('span#contact_info_phone')?.innerText;
+ const url = nameToUrlMap[name] || '#';
+ // Format the contact information
+ const listItem = document.createElement('li');
+ listItem.innerHTML = `${name} , ${title}, ${email}, ${phone}`;
+ bulletList.appendChild(listItem);
+ });
+
+ }
+
+ // CASE 2 - Contacts are in a table (this happens if there is more than 2 contacts)
+ const otherContactsTable = document.querySelector('.form-row.field-other_contacts table tbody');
+ if (otherContactsTable) {
+ const otherContactsRows = otherContactsTable.querySelectorAll('tr');
+ otherContactsRows.forEach(contactRow => {
+ // Extract the contact details
+ const name = contactRow.querySelector('th').textContent.trim();
+ const title = contactRow.querySelectorAll('td')[0].textContent.trim();
+ const email = contactRow.querySelectorAll('td')[1].textContent.trim();
+ const phone = contactRow.querySelectorAll('td')[2].textContent.trim();
+ const url = nameToUrlMap[name] || '#';
+ // Format the contact information
+ const listItem = document.createElement('li');
+ listItem.innerHTML = `${name} , ${title}, ${email}, ${phone}`;
+ bulletList.appendChild(listItem);
+ });
+ }
+ otherContactsSummary += bulletList.outerHTML
+
+
+ //------ Requested Domains
+ const requestedDomainElement = document.getElementById('id_requested_domain');
+ const requestedDomain = requestedDomainElement.options[requestedDomainElement.selectedIndex].text;
+
+ //------ Submitter
+ // Function to extract text by ID and handle missing elements
+ function extractTextById(id, divElement) {
+ if (divElement) {
+ const element = divElement.querySelector(`#${id}`);
+ return element ? ", " + element.textContent.trim() : '';
+ }
+ return '';
+ }
+ // Extract the submitter name, title, email, and phone number
+ const submitterDiv = document.querySelector('.form-row.field-submitter');
+ const submitterNameElement = document.getElementById('id_submitter');
+ const submitterName = submitterNameElement.options[submitterNameElement.selectedIndex].text;
+ const submitterTitle = extractTextById('contact_info_title', submitterDiv);
+ const submitterEmail = extractTextById('contact_info_email', submitterDiv);
+ const submitterPhone = extractTextById('contact_info_phone', submitterDiv);
+ let submitterInfo = `${submitterName}${submitterTitle}${submitterEmail}${submitterPhone}`;
+
+
+ //------ Senior Official
+ const seniorOfficialDiv = document.querySelector('.form-row.field-senior_official');
+ const seniorOfficialElement = document.getElementById('id_senior_official');
+ const seniorOfficialName = seniorOfficialElement.options[seniorOfficialElement.selectedIndex].text;
+ const seniorOfficialTitle = extractTextById('contact_info_title', seniorOfficialDiv);
+ const seniorOfficialEmail = extractTextById('contact_info_email', seniorOfficialDiv);
+ const seniorOfficialPhone = extractTextById('contact_info_phone', seniorOfficialDiv);
+ let seniorOfficialInfo = `${seniorOfficialName}${seniorOfficialTitle}${seniorOfficialEmail}${seniorOfficialPhone}`;
+
+ const html_summary = `Recommendation: ` +
+ `Organization Type: ${organizationType}` +
+ `Requested Domain: ${requestedDomain}` +
+ `Current Websites: ${existingWebsites.join(', ')}` +
+ `Rationale: ` +
+ `Alternative Domains: ${alternativeDomains.join(', ')}` +
+ `Submitter: ${submitterInfo}` +
+ `Senior Official: ${seniorOfficialInfo}` +
+ `Other Employees: ${otherContactsSummary}`;
+
+ //Replace with \n, then strip out all remaining html tags (replace <...> with '')
+ const plain_summary = html_summary.replace(/<\/br>| /g, '\n').replace(/<\/?[^>]+(>|$)/g, '');
+
+ // Create Blobs with the summary content
+ const html_blob = new Blob([html_summary], { type: 'text/html' });
+ const plain_blob = new Blob([plain_summary], { type: 'text/plain' });
+
+ // Create a ClipboardItem with the Blobs
+ const clipboardItem = new ClipboardItem({
+ 'text/html': html_blob,
+ 'text/plain': plain_blob
+ });
+
+ // Write the ClipboardItem to the clipboard
+ navigator.clipboard.write([clipboardItem]).then(() => {
+ // Change the icon to a checkmark on successful copy
+ let buttonIcon = copyButton.querySelector('use');
+ if (buttonIcon) {
+ let currentHref = buttonIcon.getAttribute('xlink:href');
+ let baseHref = currentHref.split('#')[0];
+
+ // Append the new icon reference
+ buttonIcon.setAttribute('xlink:href', baseHref + '#check');
+
+ // Change the button text
+ nearestSpan = copyButton.querySelector("span")
+ original_text = nearestSpan.innerText
+ nearestSpan.innerText = "Copied to clipboard"
+
+ setTimeout(function() {
+ // Change back to the copy icon
+ buttonIcon.setAttribute('xlink:href', currentHref);
+ nearestSpan.innerText = original_text
+ }, 2000);
+
+ }
+ console.log('Summary copied to clipboard successfully!');
+ }).catch(err => {
+ console.error('Failed to copy text: ', err);
+ });
+ });
+ }
+})();
diff --git a/src/registrar/assets/sass/_theme/_admin.scss b/src/registrar/assets/sass/_theme/_admin.scss
index d7d116046..711bfe960 100644
--- a/src/registrar/assets/sass/_theme/_admin.scss
+++ b/src/registrar/assets/sass/_theme/_admin.scss
@@ -369,9 +369,6 @@ input.admin-confirm-button {
padding: 10px 8px;
line-height: normal;
}
- .usa-icon {
- top: 2px;
- }
a.button:active, a.button:focus {
text-decoration: none;
}
@@ -447,15 +444,12 @@ address.margin-top-neg-1__detail-list {
}
}
-td button.usa-button__clipboard-link, address.dja-address-contact-list {
+address.dja-address-contact-list {
font-size: unset;
}
address.dja-address-contact-list {
color: var(--body-quiet-color);
- button.usa-button__clipboard-link {
- font-size: unset;
- }
}
// Mimic the normal label size
@@ -464,11 +458,18 @@ address.dja-address-contact-list {
font-size: 0.875rem;
color: var(--body-quiet-color);
}
+}
- address button.usa-button__clipboard-link, td button.usa-button__clipboard-link {
- font-size: 0.875rem !important;
- }
+// Targets the unstyled buttons in the form
+.button--clipboard {
+ color: var(--link-fg);
+}
+// Targets the DJA buttom with a nested icon
+button .usa-icon,
+.button .usa-icon,
+.button--clipboard .usa-icon {
+ vertical-align: middle;
}
.errors span.select2-selection {
@@ -663,7 +664,7 @@ address.dja-address-contact-list {
align-items: center;
- .usa-button__icon {
+ .usa-button--icon {
position: absolute;
right: auto;
left: 4px;
@@ -681,10 +682,6 @@ address.dja-address-contact-list {
}
}
-button.usa-button__clipboard {
- color: var(--link-fg);
-}
-
.no-outline-on-click:focus {
outline: none !important;
}
diff --git a/src/registrar/assets/sass/_theme/_buttons.scss b/src/registrar/assets/sass/_theme/_buttons.scss
index 7fa379c0b..d246366d8 100644
--- a/src/registrar/assets/sass/_theme/_buttons.scss
+++ b/src/registrar/assets/sass/_theme/_buttons.scss
@@ -213,4 +213,4 @@ a.usa-button--unstyled:visited {
.margin-right-neg-4px {
margin-right: -4px;
-}
+}
\ No newline at end of file
diff --git a/src/registrar/assets/sass/_theme/_links.scss b/src/registrar/assets/sass/_theme/_links.scss
index e9b71733a..fd1c3dee9 100644
--- a/src/registrar/assets/sass/_theme/_links.scss
+++ b/src/registrar/assets/sass/_theme/_links.scss
@@ -15,3 +15,4 @@
margin-right: units(0.5);
}
}
+
diff --git a/src/registrar/assets/sass/_theme/styles.scss b/src/registrar/assets/sass/_theme/styles.scss
index 4775b60c9..f9df015b4 100644
--- a/src/registrar/assets/sass/_theme/styles.scss
+++ b/src/registrar/assets/sass/_theme/styles.scss
@@ -27,4 +27,4 @@
/*--------------------------------------------------
--- Admin ---------------------------------*/
-@forward "admin";
+@forward "admin";
\ No newline at end of file
diff --git a/src/registrar/config/settings.py b/src/registrar/config/settings.py
index 3da0a104a..9d707a533 100644
--- a/src/registrar/config/settings.py
+++ b/src/registrar/config/settings.py
@@ -241,7 +241,6 @@ TEMPLATES = [
"registrar.context_processors.is_demo_site",
"registrar.context_processors.is_production",
"registrar.context_processors.org_user_status",
- "registrar.context_processors.add_portfolio_to_context",
"registrar.context_processors.add_path_to_context",
"registrar.context_processors.add_has_profile_feature_flag_to_context",
"registrar.context_processors.portfolio_permissions",
@@ -665,6 +664,7 @@ ALLOWED_HOSTS = [
"getgov-stable.app.cloud.gov",
"getgov-staging.app.cloud.gov",
"getgov-development.app.cloud.gov",
+ "getgov-ad.app.cloud.gov",
"getgov-ms.app.cloud.gov",
"getgov-ag.app.cloud.gov",
"getgov-litterbox.app.cloud.gov",
diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py
index 7f9db0e41..90137c4af 100644
--- a/src/registrar/config/urls.py
+++ b/src/registrar/config/urls.py
@@ -26,7 +26,6 @@ from registrar.views.domain_request import Step
from registrar.views.domain_requests_json import get_domain_requests_json
from registrar.views.domains_json import get_domains_json
from registrar.views.utility import always_404
-from registrar.views.portfolios import PortfolioDomainsView, PortfolioDomainRequestsView, PortfolioOrganizationView
from api.views import available, get_current_federal, get_current_full
@@ -61,19 +60,19 @@ for step, view in [
urlpatterns = [
path("", views.index, name="home"),
path(
- "portfolio//domains/",
- PortfolioDomainsView.as_view(),
- name="portfolio-domains",
+ "domains/",
+ views.PortfolioDomainsView.as_view(),
+ name="domains",
),
path(
- "portfolio//domain_requests/",
- PortfolioDomainRequestsView.as_view(),
- name="portfolio-domain-requests",
+ "requests/",
+ views.PortfolioDomainRequestsView.as_view(),
+ name="domain-requests",
),
path(
- "portfolio//organization/",
- PortfolioOrganizationView.as_view(),
- name="portfolio-organization",
+ "organization/",
+ views.PortfolioOrganizationView.as_view(),
+ name="organization",
),
path(
"admin/logout/",
diff --git a/src/registrar/context_processors.py b/src/registrar/context_processors.py
index 06ef07050..861a4e701 100644
--- a/src/registrar/context_processors.py
+++ b/src/registrar/context_processors.py
@@ -50,10 +50,6 @@ def org_user_status(request):
}
-def add_portfolio_to_context(request):
- return {"portfolio": getattr(request, "portfolio", None)}
-
-
def add_path_to_context(request):
return {"path": getattr(request, "path", None)}
@@ -70,11 +66,15 @@ def portfolio_permissions(request):
"has_base_portfolio_permission": False,
"has_domains_portfolio_permission": False,
"has_domain_requests_portfolio_permission": False,
+ "portfolio": None,
+ "has_organization_feature_flag": False,
}
return {
"has_base_portfolio_permission": request.user.has_base_portfolio_permission(),
"has_domains_portfolio_permission": request.user.has_domains_portfolio_permission(),
"has_domain_requests_portfolio_permission": request.user.has_domain_requests_portfolio_permission(),
+ "portfolio": request.user.portfolio,
+ "has_organization_feature_flag": flag_is_active(request, "organization_feature"),
}
except AttributeError:
# Handles cases where request.user might not exist
@@ -82,4 +82,6 @@ def portfolio_permissions(request):
"has_base_portfolio_permission": False,
"has_domains_portfolio_permission": False,
"has_domain_requests_portfolio_permission": False,
+ "portfolio": None,
+ "has_organization_feature_flag": False,
}
diff --git a/src/registrar/fixtures_users.py b/src/registrar/fixtures_users.py
index 74fd4d15d..7ce63d364 100644
--- a/src/registrar/fixtures_users.py
+++ b/src/registrar/fixtures_users.py
@@ -22,6 +22,11 @@ class UserFixture:
"""
ADMINS = [
+ {
+ "username": "aad084c3-66cc-4632-80eb-41cdf5c5bcbf",
+ "first_name": "Aditi",
+ "last_name": "Green",
+ },
{
"username": "be17c826-e200-4999-9389-2ded48c43691",
"first_name": "Matthew",
@@ -120,6 +125,11 @@ class UserFixture:
]
STAFF = [
+ {
+ "username": "ffec5987-aa84-411b-a05a-a7ee5cbcde54",
+ "first_name": "Aditi-Analyst",
+ "last_name": "Green-Analyst",
+ },
{
"username": "d6bf296b-fac5-47ff-9c12-f88ccc5c1b99",
"first_name": "Matthew-Analyst",
diff --git a/src/registrar/models/domain_request.py b/src/registrar/models/domain_request.py
index a7252e16b..363de213b 100644
--- a/src/registrar/models/domain_request.py
+++ b/src/registrar/models/domain_request.py
@@ -215,6 +215,11 @@ class DomainRequest(TimeStampedModel):
}
return org_election_map
+ @classmethod
+ def get_org_label(cls, org_name: str):
+ # Translating the key that is given to the direct readable value
+ return cls(org_name).label if org_name else None
+
class OrganizationChoicesVerbose(models.TextChoices):
"""
Tertiary organization choices
diff --git a/src/registrar/registrar_middleware.py b/src/registrar/registrar_middleware.py
index dd9b5541a..2af331bc9 100644
--- a/src/registrar/registrar_middleware.py
+++ b/src/registrar/registrar_middleware.py
@@ -149,10 +149,10 @@ class CheckPortfolioMiddleware:
request.portfolio = portfolio
if request.user.has_domains_portfolio_permission():
- portfolio_redirect = reverse("portfolio-domains", kwargs={"portfolio_id": portfolio.id})
+ portfolio_redirect = reverse("domains")
else:
# View organization is the lowest access
- portfolio_redirect = reverse("portfolio-organization", kwargs={"portfolio_id": portfolio.id})
+ portfolio_redirect = reverse("organization")
return HttpResponseRedirect(portfolio_redirect)
diff --git a/src/registrar/templates/admin/change_form.html b/src/registrar/templates/admin/change_form.html
index 78dac9ac0..f2ac7f2df 100644
--- a/src/registrar/templates/admin/change_form.html
+++ b/src/registrar/templates/admin/change_form.html
@@ -1,4 +1,5 @@
{% extends "admin/change_form.html" %}
+{% load static i18n %}
{% comment %} Replace the Django ul markup with a div. We'll edit the child markup accordingly in change_form_object_tools {% endcomment %}
{% block object-tools %}
@@ -9,4 +10,4 @@
{% endblock %}
{% endif %}
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/src/registrar/templates/admin/change_form_object_tools.html b/src/registrar/templates/admin/change_form_object_tools.html
index 28c655bbc..198140c19 100644
--- a/src/registrar/templates/admin/change_form_object_tools.html
+++ b/src/registrar/templates/admin/change_form_object_tools.html
@@ -1,4 +1,5 @@
{% load i18n admin_urls %}
+{% load i18n static %}
{% comment %} Replace li with p for more semantic HTML if we have a single child {% endcomment %}
{% block object-tools-items %}
@@ -13,8 +14,21 @@
{% else %}
-
- {% translate "History" %}
-
+
{% endif %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
+
diff --git a/src/registrar/templates/admin/input_with_clipboard.html b/src/registrar/templates/admin/input_with_clipboard.html
index 20a029bed..ea2fbce33 100644
--- a/src/registrar/templates/admin/input_with_clipboard.html
+++ b/src/registrar/templates/admin/input_with_clipboard.html
@@ -8,7 +8,7 @@ Template for an input field with a clipboard
{{ field }}
@@ -25,7 +25,7 @@ Template for an input field with a clipboard
+
{% if show_formatted_name %}
{% if user.get_formatted_name %}
- {{ user.get_formatted_name }}
+ {{ user.get_formatted_name }}
{% else %}
- None
+ None
{% endif %}
{% endif %}
+
{% if user.has_contact_info %}
{# Title #}
{% if user.title %}
- {{ user.title }}
-
+ {{ user.title }}
{% else %}
- None
+ None
{% endif %}
+
+
{# Email #}
{% if user.email %}
- {{ user.email }}
+ {{ user.email }}
{% include "admin/input_with_clipboard.html" with field=user invisible_input_field=True %}
{% else %}
@@ -29,7 +32,7 @@
{# Phone #}
{% if user.phone %}
- {{ user.phone }}
+ {{ user.phone }}
{% else %}
None
@@ -40,6 +43,6 @@
{% endif %}
{% if user_verification_type %}
- {{ user_verification_type }}
+ {{ user_verification_type }}
{% endif %}
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
index 7765b9203..ff277a444 100644
--- a/src/registrar/templates/django/admin/includes/descriptions/domain_invitation_description.html
+++ b/src/registrar/templates/django/admin/includes/descriptions/domain_invitation_description.html
@@ -5,8 +5,8 @@ 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.
+An “invited” status indicates that the recipient has not logged in to the registrar since the invitation was sent. Deleting an invitation with an "invited" status will prevent the user from signing in.
+A “received” status indicates that the recipient has logged in. Deleting an invitation with a "received" status will not revoke that user's access from the domain. To remove a user who has already signed in, go to User domain roles and delete the role for the correct domain/manager combination.
diff --git a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
index 51dd9b518..067b69c07 100644
--- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
+++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html
@@ -219,7 +219,7 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
+
+
+ To manage information for this domain, you must add yourself as a domain manager.
+
+
+
+ {% endif %}
+
+
{% url 'domain-dns-nameservers' pk=domain.id as url %}
{% if domain.nameservers|length > 0 %}
- {% include "includes/summary_item.html" with title='DNS name servers' domains='true' value=domain.nameservers list='true' edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='DNS name servers' domains='true' value=domain.nameservers list='true' edit_link=url editable=is_editable %}
{% else %}
- {% if domain.is_editable %}
+ {% if is_editable %}
DNS name servers
No DNS name servers have been added yet. Before your domain can be used we’ll need information about your domain name servers.
Add DNS name servers
{% else %}
- {% include "includes/summary_item.html" with title='DNS name servers' domains='true' value='' edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='DNS name servers' domains='true' value='' edit_link=url editable=is_editable %}
{% endif %}
{% endif %}
{% url 'domain-org-name-address' pk=domain.id as url %}
- {% include "includes/summary_item.html" with title='Organization name and mailing address' value=domain.domain_info address='true' edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='Organization name and mailing address' value=domain.domain_info address='true' edit_link=url editable=is_editable %}
{% url 'domain-senior-official' pk=domain.id as url %}
- {% include "includes/summary_item.html" with title='Senior official' value=domain.domain_info.senior_official contact='true' edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='Senior official' value=domain.domain_info.senior_official contact='true' edit_link=url editable=is_editable %}
{# Conditionally display profile #}
{% if not has_profile_feature_flag %}
{% url 'domain-your-contact-information' pk=domain.id as url %}
- {% include "includes/summary_item.html" with title='Your contact information' value=request.user contact='true' edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='Your contact information' value=request.user contact='true' edit_link=url editable=is_editable %}
{% endif %}
{% url 'domain-security-email' pk=domain.id as url %}
{% if security_email is not None and security_email not in hidden_security_emails%}
- {% include "includes/summary_item.html" with title='Security email' value=security_email edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='Security email' value=security_email edit_link=url editable=is_editable %}
{% else %}
- {% include "includes/summary_item.html" with title='Security email' value='None provided' edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='Security email' value='None provided' edit_link=url editable=is_editable %}
{% endif %}
{% url 'domain-users' pk=domain.id as url %}
- {% include "includes/summary_item.html" with title='Domain managers' users='true' list=True value=domain.permissions.all edit_link=url editable=domain.is_editable %}
+ {% include "includes/summary_item.html" with title='Domain managers' users='true' list=True value=domain.permissions.all edit_link=url editable=is_editable %}
{% endblock %} {# domain_content #}
diff --git a/src/registrar/templates/domain_sidebar.html b/src/registrar/templates/domain_sidebar.html
index d61e5f45c..603822d0d 100644
--- a/src/registrar/templates/domain_sidebar.html
+++ b/src/registrar/templates/domain_sidebar.html
@@ -12,7 +12,7 @@
- {% if domain.is_editable %}
+ {% if is_editable %}
{% url 'domain-dns' pk=domain.id as url %}
diff --git a/src/registrar/templates/includes/domains_table.html b/src/registrar/templates/includes/domains_table.html
index ba9a8dcb7..bce89fd12 100644
--- a/src/registrar/templates/includes/domains_table.html
+++ b/src/registrar/templates/includes/domains_table.html
@@ -1,11 +1,9 @@
{% load static %}