diff --git a/.github/ISSUE_TEMPLATE/developer-onboarding.md b/.github/ISSUE_TEMPLATE/developer-onboarding.md index eb547d5ab..d63cf2f94 100644 --- a/.github/ISSUE_TEMPLATE/developer-onboarding.md +++ b/.github/ISSUE_TEMPLATE/developer-onboarding.md @@ -19,12 +19,13 @@ There are several tools we use locally that you will need to have. - If you are using Windows, installation information can be found [here](https://github.com/cloudfoundry/cli/wiki/V8-CLI-Installation-Guide#installers-and-compressed-binaries) - Alternatively, for Windows, [consider using chocolately](https://community.chocolatey.org/packages/cloudfoundry-cli/7.2.0) - [ ] Make sure you have `gpg` >2.1.7. Run `gpg --version` to check. If not, [install gnupg](https://formulae.brew.sh/formula/gnupg) + - Alternatively, you can skip this step and [use ssh keys](#setting-up-commit-signing-with-ssh) instead - [ ] Install the [Github CLI](https://cli.github.com/) ## Access ### Steps for the onboardee -- [ ] Setup [commit signing in Github](#setting-up-commit-signing) and with git locally. +- [ ] Setup commit signing in Github and with git locally using either [gpg](#setting-up-commit-signing-with-gpg) or [ssh](#setting-up-commit-signing-with-ssh). - [ ] [Create a cloud.gov account](https://cloud.gov/docs/getting-started/accounts/) - [ ] Email github@cisa.dhs.gov (cc: Cameron) to add you to the [CISA Github organization](https://github.com/getgov) and [.gov Team](https://github.com/orgs/cisagov/teams/gov). - [ ] Ensure you can login to your cloud.gov account via the CLI @@ -51,7 +52,7 @@ cf login -a api.fr.cloud.gov --sso - [ ] [Contributing Policy](https://github.com/cisagov/dotgov/tree/main/CONTRIBUTING.md) -## Setting up commit signing +## Setting up commit signing with GPG Follow the instructions [here](https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key) to generate a new GPG key (default configurations are okay) and add it to your GPG keys on Github. @@ -72,6 +73,22 @@ when setting up your key in Github. Now test commit signing is working by checking out a branch (`yourname/test-commit-signing`) and making some small change to a file. Commit the change (it should prompt you for your GPG credential) and push it to Github. Look on Github at your branch and ensure the commit is `verified`. +## Setting up commit signing with SSH + +Follow the instructions [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key) to generate a new SSH key and [add it to your SSH keys on Github](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account). Note that you need to add the key as a signing key. + +Configure your key locally: + +```bash +git config --global gpg.format ssh +git config --global commit.gpgsign true +git config --global user.signingkey +``` + +Where `` is the path to the private key you generated when running `ssh-keygen`. Usually this is located in ~\.ssh\. + +Now test commit signing is working by checking out a branch (`yourinitials/test-commit-signing`) and making some small change to a file. Commit the change (it should prompt you for your key passphrase) and push it to Github. Look on Github at your branch and ensure the commit is `verified`. + ### MacOS **Note:** if you are on a mac and not able to successfully create a signed commit, getting the following error: ```zsh diff --git a/.github/workflows/createcachetable.yaml b/.github/workflows/createcachetable.yaml index 8fa4d76c8..207ecf70e 100644 --- a/.github/workflows/createcachetable.yaml +++ b/.github/workflows/createcachetable.yaml @@ -28,6 +28,7 @@ on: - ab - rjm - dk + - ms jobs: createcachetable: diff --git a/.github/workflows/deploy-branch-to-sandbox.yaml b/.github/workflows/deploy-branch-to-sandbox.yaml new file mode 100644 index 000000000..f57961fa8 --- /dev/null +++ b/.github/workflows/deploy-branch-to-sandbox.yaml @@ -0,0 +1,92 @@ +# Manually deploy a branch of choice to an environment of choice. + +name: Manual Build and Deploy +run-name: Manually build and deploy branch to sandbox of choice + +on: + workflow_dispatch: + inputs: + environment: + description: 'Environment to deploy' + required: true + default: 'backup' + type: 'choice' + options: + - ab + - backup + - cb + - dk + - es + - gd + - ko + - ky + - nl + - rb + - rh + - rjm + - meoward + - bob + - hotgov + - litterbox + - ms + # GitHub Actions has no "good" way yet to dynamically input branches + branch: + description: 'Branch to deploy' + required: true + default: 'main' + type: string + + +jobs: + variables: + runs-on: ubuntu-latest + steps: + - name: Setting global variables + uses: actions/github-script@v6 + id: var + with: + script: | + core.setOutput('environment', '${{ github.head_ref }}'.split("/")[0]); + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Compile USWDS assets + working-directory: ./src + run: | + docker compose run node npm install npm@latest && + docker compose run node npm install && + docker compose run node npx gulp copyAssets && + docker compose run node npx gulp compile + - name: Collect static assets + working-directory: ./src + run: docker compose run app python manage.py collectstatic --no-input + - name: Deploy to cloud.gov sandbox + uses: cloud-gov/cg-cli-tools@main + env: + ENVIRONMENT: ${{ github.event.inputs.environment }} + CF_USERNAME: CF_${{ github.event.inputs.environment }}_USERNAME + CF_PASSWORD: CF_${{ github.event.inputs.environment }}_PASSWORD + with: + cf_username: ${{ secrets[env.CF_USERNAME] }} + cf_password: ${{ secrets[env.CF_PASSWORD] }} + cf_org: cisa-dotgov + cf_space: ${{ env.ENVIRONMENT }} + cf_manifest: ops/manifests/manifest-${{ env.ENVIRONMENT }}.yaml + comment: + runs-on: ubuntu-latest + needs: [deploy] + steps: + - uses: actions/github-script@v6 + env: + ENVIRONMENT: ${{ github.event.inputs.environment }} + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + body: '🥳 Successfully deployed to developer sandbox **[${{ env.ENVIRONMENT }}](https://getgov-${{ env.ENVIRONMENT }}.app.cloud.gov/)**.' + }) + + diff --git a/.github/workflows/deploy-development.yaml b/.github/workflows/deploy-development.yaml index 03994e1de..fa447ed76 100644 --- a/.github/workflows/deploy-development.yaml +++ b/.github/workflows/deploy-development.yaml @@ -22,7 +22,8 @@ jobs: - name: Compile USWDS assets working-directory: ./src run: | - docker compose run node npm install && + docker compose run node npm install npm@latest && + docker compose run node npm install && docker compose run node npx gulp copyAssets && docker compose run node npx gulp compile - name: Collect static assets diff --git a/.github/workflows/deploy-sandbox.yaml b/.github/workflows/deploy-sandbox.yaml index 4bd7f99dd..57561919c 100644 --- a/.github/workflows/deploy-sandbox.yaml +++ b/.github/workflows/deploy-sandbox.yaml @@ -47,7 +47,8 @@ jobs: - name: Compile USWDS assets working-directory: ./src run: | - docker compose run node npm install && + docker compose run node npm install npm@latest && + docker compose run node npm install && docker compose run node npx gulp copyAssets && docker compose run node npx gulp compile - name: Collect static assets diff --git a/.github/workflows/issue-label-notifier.yaml b/.github/workflows/issue-label-notifier.yaml new file mode 100644 index 000000000..c4f10d48f --- /dev/null +++ b/.github/workflows/issue-label-notifier.yaml @@ -0,0 +1,18 @@ +name: Notify users based on issue labels + +on: + issues: + types: [labeled] + pull_request: + types: [labeled] + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - uses: jenschelkopf/issue-label-notification-action@1.3 + with: + recipients: | + design-review=@Katherine-Osos + message: 'cc/ {recipients} — adding you to this **{label}** issue!' + \ No newline at end of file diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py index bdd61b346..6ebe25d45 100644 --- a/src/djangooidc/tests/test_views.py +++ b/src/djangooidc/tests/test_views.py @@ -429,6 +429,10 @@ class ViewsTest(TestCase): # Create a mock request request = self.factory.get("/some-url") request.session = {"acr_value": ""} + # Mock user and its attributes + mock_user = MagicMock() + mock_user.is_authenticated = True + request.user = mock_user # Ensure that the CLIENT instance used in login_callback is the mock # patch _requires_step_up_auth to return False with patch("djangooidc.views._requires_step_up_auth", return_value=False), patch( diff --git a/src/docker-compose.yml b/src/docker-compose.yml index 39282ff96..d64ba80d5 100644 --- a/src/docker-compose.yml +++ b/src/docker-compose.yml @@ -1,4 +1,3 @@ -version: "3.0" services: app: build: . diff --git a/src/registrar/admin.py b/src/registrar/admin.py index d7bc662e3..5739fe2c9 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -741,6 +741,7 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin): "last_name", "title", "email", + "phone", "Permissions", "is_active", "groups", @@ -1383,7 +1384,7 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin): for name, data in fieldsets: fields = data.get("fields", []) fields = tuple(field for field in fields if field not in DomainInformationAdmin.superuser_only_fields) - modified_fieldsets.append((name, {"fields": fields})) + modified_fieldsets.append((name, {**data, "fields": fields})) return modified_fieldsets return fieldsets @@ -1644,7 +1645,6 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): "is_election_board", "federal_agency", "status_history", - "action_needed_reason_email", ) # Read only that we'll leverage for CISA Analysts @@ -1698,7 +1698,7 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): for name, data in fieldsets: fields = data.get("fields", []) fields = tuple(field for field in fields if field not in self.superuser_only_fields) - modified_fieldsets.append((name, {"fields": fields})) + modified_fieldsets.append((name, {**data, "fields": fields})) return modified_fieldsets return fieldsets @@ -1745,29 +1745,39 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): if not change: return super().save_model(request, obj, form, change) - # == Handle non-status changes == # - # Change this in #1901. Add a check on "not self.action_needed_reason_email" - if obj.action_needed_reason: - self._handle_action_needed_reason_email(obj) - should_save = True - # Get the original domain request from the database. original_obj = models.DomainRequest.objects.get(pk=obj.pk) + + # == Handle action_needed_reason == # + + reason_changed = obj.action_needed_reason != original_obj.action_needed_reason + if reason_changed: + # Track the fact that we sent out an email + request.session["action_needed_email_sent"] = True + + # Set the action_needed_reason_email to the default if nothing exists. + # Since this check occurs after save, if the user enters a value then we won't update. + + default_email = self._get_action_needed_reason_default_email(obj, obj.action_needed_reason) + if obj.action_needed_reason_email: + emails = self.get_all_action_needed_reason_emails(obj) + is_custom_email = obj.action_needed_reason_email not in emails.values() + if not is_custom_email: + obj.action_needed_reason_email = default_email + else: + obj.action_needed_reason_email = default_email + + # == Handle status == # if obj.status == original_obj.status: # If the status hasn't changed, let the base function take care of it return super().save_model(request, obj, form, change) + else: + # Run some checks on the current object for invalid status changes + obj, should_save = self._handle_status_change(request, obj, original_obj) - # == Handle status changes == # - # Run some checks on the current object for invalid status changes - obj, should_save = self._handle_status_change(request, obj, original_obj) - - # We should only save if we don't display any errors in the steps above. - if should_save: - return super().save_model(request, obj, form, change) - - def _handle_action_needed_reason_email(self, obj): - text = self._get_action_needed_reason_default_email_text(obj, obj.action_needed_reason) - obj.action_needed_reason_email = text.get("email_body_text") + # We should only save if we don't display any errors in the steps above. + if should_save: + return super().save_model(request, obj, form, change) def _handle_status_change(self, request, obj, original_obj): """ @@ -1962,49 +1972,54 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin): # Initialize extra_context and add filtered entries extra_context = extra_context or {} extra_context["filtered_audit_log_entries"] = filtered_audit_log_entries - extra_context["action_needed_reason_emails"] = self.get_all_action_needed_reason_emails_as_json(obj) + emails = self.get_all_action_needed_reason_emails(obj) + extra_context["action_needed_reason_emails"] = json.dumps(emails) extra_context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature") + # Denote if an action needed email was sent or not + email_sent = request.session.get("action_needed_email_sent", False) + extra_context["action_needed_email_sent"] = email_sent + if email_sent: + request.session["action_needed_email_sent"] = False + # Call the superclass method with updated extra_context return super().change_view(request, object_id, form_url, extra_context) - def get_all_action_needed_reason_emails_as_json(self, domain_request): + def get_all_action_needed_reason_emails(self, domain_request): """Returns a json dictionary of every action needed reason and its associated email for this particular domain request.""" + emails = {} for action_needed_reason in domain_request.ActionNeededReasons: - enum_value = action_needed_reason.value - # Change this in #1901. Just add a check for the current value. - emails[enum_value] = self._get_action_needed_reason_default_email_text(domain_request, enum_value) - return json.dumps(emails) + # Map the action_needed_reason to its default email + emails[action_needed_reason.value] = self._get_action_needed_reason_default_email( + domain_request, action_needed_reason.value + ) - def _get_action_needed_reason_default_email_text(self, domain_request, action_needed_reason: str): + return emails + + def _get_action_needed_reason_default_email(self, domain_request, action_needed_reason): """Returns the default email associated with the given action needed reason""" - if action_needed_reason is None or action_needed_reason == domain_request.ActionNeededReasons.OTHER: - return { - "subject_text": None, - "email_body_text": None, - } - - # Get the email body - template_path = f"emails/action_needed_reasons/{action_needed_reason}.txt" - template = get_template(template_path) - - # Get the email subject - template_subject_path = f"emails/action_needed_reasons/{action_needed_reason}_subject.txt" - subject_template = get_template(template_subject_path) + if not action_needed_reason or action_needed_reason == DomainRequest.ActionNeededReasons.OTHER: + return None if flag_is_active(None, "profile_feature"): # type: ignore recipient = domain_request.creator else: recipient = domain_request.submitter - # Return the content of the rendered views + # Return the context of the rendered views context = {"domain_request": domain_request, "recipient": recipient} - return { - "subject_text": subject_template.render(context=context), - "email_body_text": template.render(context=context), - } + + # Get the email body + template_path = f"emails/action_needed_reasons/{action_needed_reason}.txt" + + email_body_text = get_template(template_path).render(context=context) + email_body_text_cleaned = None + if email_body_text: + email_body_text_cleaned = email_body_text.strip().lstrip("\n") + + return email_body_text_cleaned def process_log_entry(self, log_entry): """Process a log entry and return filtered entry dictionary if applicable.""" diff --git a/src/registrar/assets/js/get-gov-admin.js b/src/registrar/assets/js/get-gov-admin.js index 4797e2d21..d8bc21899 100644 --- a/src/registrar/assets/js/get-gov-admin.js +++ b/src/registrar/assets/js/get-gov-admin.js @@ -36,6 +36,15 @@ function openInNewTab(el, removeAttribute = false){ } }; +// Adds or removes a boolean from our session +function addOrRemoveSessionBoolean(name, add){ + if (add) { + sessionStorage.setItem(name, "true"); + }else { + sessionStorage.removeItem(name); + } +} + // <<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>> // Event handlers. @@ -420,15 +429,6 @@ function initializeWidgetOnList(list, parentId) { object.classList.add("display-none"); } } - - // Adds or removes a boolean from our session - function addOrRemoveSessionBoolean(name, add){ - if (add) { - sessionStorage.setItem(name, "true"); - }else { - sessionStorage.removeItem(name); - } - } })(); /** An IIFE for toggling the submit bar on domain request forms @@ -528,54 +528,80 @@ function initializeWidgetOnList(list, parentId) { * This shows the auto generated email on action needed reason. */ (function () { - let actionNeededReasonDropdown = document.querySelector("#id_action_needed_reason"); - let actionNeededEmail = document.querySelector("#action_needed_reason_email_view_more"); - if(actionNeededReasonDropdown && actionNeededEmail) { - // Add a change listener to the action needed reason dropdown - handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail); - } + // Since this is an iife, these vars will be removed from memory afterwards + var actionNeededReasonDropdown = document.querySelector("#id_action_needed_reason"); + var actionNeededEmail = document.querySelector("#id_action_needed_reason_email"); + var readonlyView = document.querySelector("#action-needed-reason-email-readonly"); - function handleChangeActionNeededEmail(actionNeededReasonDropdown, actionNeededEmail) { - actionNeededReasonDropdown.addEventListener("change", function() { + let emailWasSent = document.getElementById("action-needed-email-sent"); + let actionNeededEmailData = document.getElementById('action-needed-emails-data').textContent; + let actionNeededEmailsJson = JSON.parse(actionNeededEmailData); + + const domainRequestId = actionNeededReasonDropdown ? document.querySelector("#domain_request_id").value : null + const emailSentSessionVariableName = `actionNeededEmailSent-${domainRequestId}`; + const oldDropdownValue = actionNeededReasonDropdown ? actionNeededReasonDropdown.value : null; + const oldEmailValue = actionNeededEmailData ? actionNeededEmailData.value : null; + + if(actionNeededReasonDropdown && actionNeededEmail && domainRequestId) { + // Add a change listener to dom load + document.addEventListener('DOMContentLoaded', function() { let reason = actionNeededReasonDropdown.value; - // If a reason isn't specified, no email will be sent. - // You also cannot save the model in this state. - // This flow occurs if you switch back to the empty picker state. - if(!reason) { - showNoEmailMessage(actionNeededEmail); - return; - } - - let actionNeededEmails = JSON.parse(document.getElementById('action-needed-emails-data').textContent) - let emailData = actionNeededEmails[reason]; - if (emailData) { - let emailBody = emailData.email_body_text - if (emailBody) { - actionNeededEmail.value = emailBody - showActionNeededEmail(actionNeededEmail); - }else { - showNoEmailMessage(actionNeededEmail); - } - }else { - showNoEmailMessage(actionNeededEmail); + // Handle the session boolean (to enable/disable editing) + if (emailWasSent && emailWasSent.value === "True") { + // An email was sent out - store that information in a session variable + addOrRemoveSessionBoolean(emailSentSessionVariableName, add=true); } + // Show an editable email field or a readonly one + updateActionNeededEmailDisplay(reason) + }); + + // Add a change listener to the action needed reason dropdown + actionNeededReasonDropdown.addEventListener("change", function() { + let reason = actionNeededReasonDropdown.value; + let emailBody = reason in actionNeededEmailsJson ? actionNeededEmailsJson[reason] : null; + if (reason && emailBody) { + // Replace the email content + actionNeededEmail.value = emailBody; + + // Reset the session object on change since change refreshes the email content. + if (oldDropdownValue !== actionNeededReasonDropdown.value || oldEmailValue !== actionNeededEmail.value) { + let emailSent = sessionStorage.getItem(emailSentSessionVariableName) + if (emailSent !== null){ + addOrRemoveSessionBoolean(emailSentSessionVariableName, add=false) + } + } + } + + // Show an editable email field or a readonly one + updateActionNeededEmailDisplay(reason) }); } - // Show the text field. Hide the "no email" message. - function showActionNeededEmail(actionNeededEmail){ - let noEmailMessage = document.getElementById("no-email-message"); - showElement(actionNeededEmail); - hideElement(noEmailMessage); + // Shows an editable email field or a readonly one. + // If the email doesn't exist or if we're of reason "other", display that no email was sent. + // Likewise, if we've sent this email before, we should just display the content. + function updateActionNeededEmailDisplay(reason) { + let emailHasBeenSentBefore = sessionStorage.getItem(emailSentSessionVariableName) !== null; + let collapseableDiv = readonlyView.querySelector(".collapse--dgsimple"); + let showMoreButton = document.querySelector("#action_needed_reason_email__show_details"); + if ((reason && reason != "other") && !emailHasBeenSentBefore) { + showElement(actionNeededEmail.parentElement) + hideElement(readonlyView) + hideElement(showMoreButton) + } else { + if (!reason || reason === "other") { + collapseableDiv.innerHTML = reason ? "No email will be sent." : "-"; + hideElement(showMoreButton) + if (collapseableDiv.classList.contains("collapsed")) { + showMoreButton.click() + } + }else { + showElement(showMoreButton) + } + hideElement(actionNeededEmail.parentElement) + showElement(readonlyView) + } } - - // Hide the text field. Show the "no email" message. - function showNoEmailMessage(actionNeededEmail) { - let noEmailMessage = document.getElementById("no-email-message"); - hideElement(actionNeededEmail); - showElement(noEmailMessage); - } - })(); diff --git a/src/registrar/assets/js/get-gov.js b/src/registrar/assets/js/get-gov.js index 7052d786f..f83966756 100644 --- a/src/registrar/assets/js/get-gov.js +++ b/src/registrar/assets/js/get-gov.js @@ -1140,6 +1140,7 @@ document.addEventListener('DOMContentLoaded', function() { const statusCheckboxes = document.querySelectorAll('input[name="filter-status"]'); const statusIndicator = document.querySelector('.domain__filter-indicator'); const statusToggle = document.querySelector('.usa-button--filter'); + const noPortfolioFlag = document.getElementById('no-portfolio-js-flag'); /** * Loads rows in the domains list, as well as updates pagination around the domains list @@ -1173,8 +1174,20 @@ document.addEventListener('DOMContentLoaded', function() { const expirationDateFormatted = expirationDate ? expirationDate.toLocaleDateString('en-US', options) : ''; const expirationDateSortValue = expirationDate ? expirationDate.getTime() : ''; const actionUrl = domain.action_url; + const suborganization = domain.suborganization ? domain.suborganization : ''; const row = document.createElement('tr'); + + let markupForSuborganizationRow = ''; + + if (!noPortfolioFlag) { + markupForSuborganizationRow = ` + + ${suborganization} + + ` + } + row.innerHTML = ` ${domain.name} @@ -1195,6 +1208,7 @@ document.addEventListener('DOMContentLoaded', function() { + ${markupForSuborganizationRow}
{% endblock %} - {% block banner %} -
- -
- {% endblock banner %} +
+ {% block header %} + {% include "includes/header_selector.html" with logo_clickable=True %} + {% endblock header %} {% block wrapper %}
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 8b8748f80..51dd9b518 100644 --- a/src/registrar/templates/django/admin/includes/detail_table_fieldset.html +++ b/src/registrar/templates/django/admin/includes/detail_table_fieldset.html @@ -143,6 +143,28 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html) {% endwith %} {% endblock field_readonly %} +{% block field_other %} + {% if field.field.name == "action_needed_reason_email" %} + +
+ {{ field.field }} + +
+ {% else %} + {{ field.field }} + {% endif %} +{% endblock field_other %} + {% block after_help_text %} {% if field.field.name == "action_needed_reason_email" %} {% comment %} diff --git a/src/registrar/templates/emails/action_needed_reasons/custom_email.txt b/src/registrar/templates/emails/action_needed_reasons/custom_email.txt new file mode 100644 index 000000000..58e539816 --- /dev/null +++ b/src/registrar/templates/emails/action_needed_reasons/custom_email.txt @@ -0,0 +1,3 @@ +{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #} +{{ custom_email_content }} +{% endautoescape %} diff --git a/src/registrar/templates/emails/status_change_rejected.txt b/src/registrar/templates/emails/status_change_rejected.txt index e377b12ff..12693deb9 100644 --- a/src/registrar/templates/emails/status_change_rejected.txt +++ b/src/registrar/templates/emails/status_change_rejected.txt @@ -42,13 +42,11 @@ Your domain request was rejected because we determined that {{ domain_request.or eligible for a .gov domain. .Gov domains are only available to official U.S.-based government organizations. +Learn more about eligibility for .gov domains +. -DEMONSTRATE ELIGIBILITY -If you can provide documentation that demonstrates your eligibility, reply to this email. -This can include links to (or copies of) your authorizing legislation, your founding -charter or bylaws, or other similar documentation. Without this, we can’t approve a -.gov domain for your organization. Learn more about eligibility for .gov domains -.{% elif domain_request.rejection_reason == 'naming_not_met' %} +If you have questions or comments, reply to this email. +{% elif domain_request.rejection_reason == 'naming_not_met' %} Your domain request was rejected because it does not meet our naming requirements. Domains should uniquely identify a government organization and be clear to the general public. Learn more about naming requirements for your type of organization diff --git a/src/registrar/templates/finish_profile_setup.html b/src/registrar/templates/finish_profile_setup.html index 6e35ad5da..61cc192bf 100644 --- a/src/registrar/templates/finish_profile_setup.html +++ b/src/registrar/templates/finish_profile_setup.html @@ -4,8 +4,8 @@ {% block title %} Finish setting up your profile | {% endblock %} {# Disable the redirect #} -{% block logo %} - {% include "includes/gov_extended_logo.html" with logo_clickable=user_finished_setup %} +{% block header %} + {% include "includes/header_selector.html" with logo_clickable=user_finished_setup %} {% endblock %} {# Add the new form #} diff --git a/src/registrar/templates/home.html b/src/registrar/templates/home.html index a5ed4c86c..b79b69ebc 100644 --- a/src/registrar/templates/home.html +++ b/src/registrar/templates/home.html @@ -10,11 +10,11 @@ {# the entire logged in page goes here #} {% block homepage_content %} -
{% block messages %} {% include "includes/form_messages.html" %} {% endblock %} +

Manage your domains

{% comment %} @@ -32,26 +32,8 @@ {% include "includes/domains_table.html" %} {% include "includes/domain_requests_table.html" %} - {# Note: Reimplement this after MVP #} - - - - - +
{% endblock %} -
{% else %} {# not user.is_authenticated #} {# the entire logged out page goes here #} diff --git a/src/registrar/templates/includes/domain_requests_table.html b/src/registrar/templates/includes/domain_requests_table.html index 4f091ecf6..efebd1e28 100644 --- a/src/registrar/templates/includes/domain_requests_table.html +++ b/src/registrar/templates/includes/domain_requests_table.html @@ -2,6 +2,7 @@
+ {% if portfolio is None %}

Domain requests

@@ -12,6 +13,9 @@