From fff440a6ff92615aab0f9dc51080a8a5850d8d74 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Mon, 26 Feb 2024 11:10:50 -0500 Subject: [PATCH 01/27] 1216 - sign-in page redesign with login.gov --- app/templates/views/signin.html | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index a19376d7cd..4ee6551273 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -13,7 +13,7 @@ {% block maincolumn_content %}
-
+
{% if again %}

You need to sign in again

@@ -29,9 +29,9 @@

You need to sign in again

{% else %}

Sign in

{% if login_gov_enabled %} - Sign in with Login.gov -

-

Or:

+

You can access your account by signing in with one of the options below:

+ Sign in with Login.gov +

Or:

{% endif %} {% endif %} @@ -41,6 +41,19 @@

Or:

{{ page_footer("Continue", secondary_link=password_reset_url, secondary_link_text="Forgot your password?") }} {% endcall %}
+
+

Notify.gov is changing the Sign in experience to Login.gov on March x, 2024

+

Why are we doing this?

+
    +
  • One single source for signing in: You can use login.gov for other sign in forms within the government
  • +
  • Security: It's really secure and trustworthy
  • +
  • Fast and easy: It's fast and easy
  • +
+
+

Don't have a login.gov account?

+

If you don't have an account already, sign up here:

+ Create Login.gov account +
{% endblock %} From 141c24e37146ff4bc80f94165715e8ce73461f4c Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Mon, 26 Feb 2024 11:07:16 -0800 Subject: [PATCH 02/27] add latest version commit hash to footer (notify-admin-204) --- .github/workflows/deploy-demo.yml | 1 + .github/workflows/deploy-prod.yml | 1 + .github/workflows/deploy.yml | 2 ++ app/config.py | 1 + app/main/forms.py | 16 +++++++---- app/main/views/api_keys.py | 22 +++++++++------ app/main/views/manage_users.py | 22 ++++++++------- app/main/views/performance.py | 6 ++-- app/main/views/send.py | 28 +++++++++++-------- app/main/views/service_settings.py | 24 ++++++++++------ app/templates/admin_template.html | 6 ++-- manifest.yml | 2 ++ tests/app/main/views/test_manage_users.py | 6 ++-- tests/app/main/views/test_template_folders.py | 8 ++++-- tests/conftest.py | 14 ++++++---- 15 files changed, 96 insertions(+), 63 deletions(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index e1d76775ab..38947c4b36 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -54,6 +54,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} + COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://idp.int.identitysandbox.gov/api/openid_connect/userinfo" diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index a0aaa81c52..de0c5714da 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -54,6 +54,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} + COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 767acae724..ac6aac9d0d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -60,6 +60,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} + COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://idp.int.identitysandbox.gov/api/openid_connect/userinfo" @@ -81,6 +82,7 @@ jobs: --var ADMIN_CLIENT_SECRET="$ADMIN_CLIENT_SECRET" --var NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY" --var NR_BROWSER_KEY="$NR_BROWSER_KEY" + --var COMMIT_HASH="$COMMIT_HASH" --var LOGIN_PEM="$LOGIN_PEM" --var LOGIN_DOT_GOV_CLIENT_ID="$LOGIN_DOT_GOV_CLIENT_ID" --var LOGIN_DOT_GOV_USER_INFO_URL="$LOGIN_DOT_GOV_USER_INFO_URL" diff --git a/app/config.py b/app/config.py index f424076fa7..91c5145091 100644 --- a/app/config.py +++ b/app/config.py @@ -36,6 +36,7 @@ class Config(object): NR_BROWSER_KEY = getenv("NR_BROWSER_KEY") settings = newrelic.agent.global_settings() NR_MONITOR_ON = settings and settings.monitor_mode + COMMIT_HASH = getenv("COMMIT_HASH") TEMPLATE_PREVIEW_API_HOST = getenv( "TEMPLATE_PREVIEW_API_HOST", "http://localhost:9999" diff --git a/app/main/forms.py b/app/main/forms.py index c01ce8fcce..2e6655cc5f 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1781,12 +1781,16 @@ def __init__( None, [ # ('email', 'Email') if 'email' in available_template_types else None, - ("sms", "Start with a blank template") - if "sms" in available_template_types - else None, - ("copy-existing", "Copy an existing template") - if allow_adding_copy_of_template - else None, + ( + ("sms", "Start with a blank template") + if "sms" in available_template_types + else None + ), + ( + ("copy-existing", "Copy an existing template") + if allow_adding_copy_of_template + else None + ), ], ) ) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index 4f8c3b29ef..8cb28ba591 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -168,12 +168,14 @@ def api_callbacks(service_id): return render_template( "views/api/callbacks.html", - received_text_messages_callback=received_text_messages_callback["url"] - if received_text_messages_callback - else None, - delivery_status_callback=delivery_status_callback["url"] - if delivery_status_callback - else None, + received_text_messages_callback=( + received_text_messages_callback["url"] + if received_text_messages_callback + else None + ), + delivery_status_callback=( + delivery_status_callback["url"] if delivery_status_callback else None + ), ) @@ -262,9 +264,11 @@ def received_text_messages_callback(service_id): received_text_messages_callback = get_received_text_messages_callback() form = CallbackForm( - url=received_text_messages_callback.get("url") - if received_text_messages_callback - else "", + url=( + received_text_messages_callback.get("url") + if received_text_messages_callback + else "" + ), bearer_token=dummy_bearer_token if received_text_messages_callback else "", ) diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 4ab20f363d..1b80c659e2 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -122,16 +122,18 @@ def edit_user_permissions(service_id, user_id): form = form_class.from_user( user, service_id, - folder_permissions=None - if user.platform_admin - else [ - f["id"] - for f in current_service.all_template_folders - if user.has_template_folder_permission(f) - ], - all_template_folders=None - if user.platform_admin - else current_service.all_template_folders, + folder_permissions=( + None + if user.platform_admin + else [ + f["id"] + for f in current_service.all_template_folders + if user.has_template_folder_permission(f) + ] + ), + all_template_folders=( + None if user.platform_admin else current_service.all_template_folders + ), ) if form.validate_on_submit(): diff --git a/app/main/views/performance.py b/app/main/views/performance.py index 13445967b6..1d2a4d1bcf 100644 --- a/app/main/views/performance.py +++ b/app/main/views/performance.py @@ -34,8 +34,8 @@ def performance(): stats["average_percentage_under_10_seconds"] = mean( [row["percentage_under_10_seconds"] for row in stats["processing_time"]] or [0] ) - stats[ - "count_of_live_services_and_organizations" - ] = status_api_client.get_count_of_live_services_and_organizations() + stats["count_of_live_services_and_organizations"] = ( + status_api_client.get_count_of_live_services_and_organizations() + ) return render_template("views/performance.html", **stats) diff --git a/app/main/views/send.py b/app/main/views/send.py index 4332c7ddbe..6c786e3acb 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -52,12 +52,14 @@ def get_example_csv_fields(column_headers, use_example_as_example, submitted_fie def get_example_csv_rows(template, use_example_as_example=True, submitted_fields=False): return { - "email": ["test@example.com"] - if use_example_as_example - else [current_user.email_address], - "sms": ["12223334444"] - if use_example_as_example - else [current_user.mobile_number], + "email": ( + ["test@example.com"] + if use_example_as_example + else [current_user.email_address] + ), + "sms": ( + ["12223334444"] if use_example_as_example else [current_user.mobile_number] + ), }[template.template_type] + get_example_csv_fields( ( placeholder @@ -511,12 +513,14 @@ def _check_messages(service_id, template_id, upload_id, preview_row): template=template, max_initial_rows_shown=50, max_errors_shown=50, - guestlist=itertools.chain.from_iterable( - [user.name, user.mobile_number, user.email_address] - for user in Users(service_id) - ) - if current_service.trial_mode - else None, + guestlist=( + itertools.chain.from_iterable( + [user.name, user.mobile_number, user.email_address] + for user in Users(service_id) + ) + if current_service.trial_mode + else None + ), remaining_messages=remaining_messages, allow_international_sms=current_service.has_permission("international_sms"), ) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 1cac1410c8..628ac59e58 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -477,9 +477,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): current_service.id, reply_to_email_id=reply_to_email_id, email_address=form.email_address.data, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), ) return redirect(url_for(".service_email_reply_to", service_id=service_id)) try: @@ -499,9 +501,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): ".service_verify_reply_to_address", service_id=service_id, notification_id=notification_id, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), replace=reply_to_email_id, ) ) @@ -702,9 +706,11 @@ def service_edit_sms_sender(service_id, sms_sender_id): service_api_client.update_sms_sender( current_service.id, sms_sender_id=sms_sender_id, - sms_sender=sms_sender["sms_sender"] - if is_inbound_number - else form.sms_sender.data.replace("\r", ""), + sms_sender=( + sms_sender["sms_sender"] + if is_inbound_number + else form.sms_sender.data.replace("\r", "") + ), is_default=True if sms_sender["is_default"] else form.is_default.data, ) return redirect(url_for(".service_sms_senders", service_id=service_id)) diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index c48f768ceb..df70151cee 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -179,7 +179,9 @@ {% if current_service and current_service.research_mode %} {% set meta_suffix = 'Built by the Technology Transformation Servicesresearch mode' %} {% else %} - {% set meta_suffix = 'Built by the Technology Transformation Services' %} + {% set commit_hash = ", Latest version: " + config['COMMIT_HASH'] %} + {% set long_link = 'Technology Transformation Services' %} + {% set meta_suffix = "Built by the " + long_link + commit_hash %} {% endif %} {{ usaFooter({ @@ -244,7 +246,7 @@ { "href": url_for('main.support'), "text": "Contact us" - }, + } ] }, ], diff --git a/manifest.yml b/manifest.yml index 1c25fdf4af..6b6c98672f 100644 --- a/manifest.yml +++ b/manifest.yml @@ -47,6 +47,8 @@ applications: REQUESTS_CA_BUNDLE: "/etc/ssl/certs/ca-certificates.crt" NEW_RELIC_CA_BUNDLE_PATH: "/etc/ssl/certs/ca-certificates.crt" + COMMIT_HASH: ((COMMIT_HASH)) + # login.gov variables LOGIN_PEM: ((LOGIN_PEM)) diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index 9bdabf9253..c3d1281556 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -862,9 +862,9 @@ def test_should_show_page_if_prefilled_user_is_already_invited( mock_get_invites_for_service, platform_admin_user, ): - active_user_with_permission_to_other_service[ - "email_address" - ] = "user_1@testnotify.gsa.gov" + active_user_with_permission_to_other_service["email_address"] = ( + "user_1@testnotify.gsa.gov" + ) client_request.login(platform_admin_user) mocker.patch( "app.models.user.user_api_client.get_user", diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index fae020e589..0bf2fcb084 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -31,9 +31,11 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): "name": name, "id": folder_id or str(uuid.uuid4()), "parent_id": parent, - "users_with_permission": users_with_permission - if users_with_permission is not None - else [sample_uuid()], + "users_with_permission": ( + users_with_permission + if users_with_permission is not None + else [sample_uuid()] + ), } diff --git a/tests/conftest.py b/tests/conftest.py index 122b768269..9019c22930 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -905,9 +905,11 @@ def create_service_templates(service_id, number_of_templates=4): "{}_template_{}".format(template_type, template_number), template_type, "{} template {} content".format(template_type, template_number), - subject="{} template {} subject".format(template_type, template_number) - if template_type == "email" - else None, + subject=( + "{} template {} subject".format(template_type, template_number) + if template_type == "email" + else None + ), ) ) @@ -1102,9 +1104,9 @@ def active_user_with_permission_to_other_service( active_user_with_permission_to_two_services["permissions"].pop(SERVICE_ONE_ID) active_user_with_permission_to_two_services["services"].pop(0) active_user_with_permission_to_two_services["name"] = "Service Two User" - active_user_with_permission_to_two_services[ - "email_address" - ] = "service-two-user@test.gsa.gov" + active_user_with_permission_to_two_services["email_address"] = ( + "service-two-user@test.gsa.gov" + ) return active_user_with_permission_to_two_services From f332587b377788ba00e4358a0159c40b52fd4bc1 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Mon, 26 Feb 2024 11:48:06 -0800 Subject: [PATCH 03/27] handle case where we are trying to build on github and haven't deployed yet --- app/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config.py b/app/config.py index 02394aa849..b1bdeafd8a 100644 --- a/app/config.py +++ b/app/config.py @@ -36,7 +36,7 @@ class Config(object): NR_BROWSER_KEY = getenv("NR_BROWSER_KEY") settings = newrelic.agent.global_settings() NR_MONITOR_ON = settings and settings.monitor_mode - COMMIT_HASH = getenv("COMMIT_HASH") + COMMIT_HASH = getenv("COMMIT_HASH", "Unknown") TEMPLATE_PREVIEW_API_HOST = getenv( "TEMPLATE_PREVIEW_API_HOST", "http://localhost:9999" From d5f40dffe1ef3bd31a05aafe943d97add4272a17 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Tue, 27 Feb 2024 11:53:51 -0500 Subject: [PATCH 04/27] Commit before merge --- app/assets/javascripts/loginAlert.js | 35 ++++++++++++++ .../uswds/_uswds-theme-custom-styles.scss | 6 +++ app/main/forms.py | 16 ++++--- app/main/views/api_keys.py | 22 +++++---- app/main/views/manage_users.py | 22 +++++---- app/main/views/performance.py | 6 +-- app/main/views/send.py | 28 ++++++----- app/main/views/service_settings.py | 24 ++++++---- app/templates/views/signin.html | 10 +++- gulpfile.js | 1 + tests/app/main/views/test_accept_invite.py | 6 +-- tests/app/main/views/test_manage_users.py | 6 +-- tests/app/main/views/test_template_folders.py | 8 ++-- tests/conftest.py | 14 +++--- tests/javascripts/loginAlert.test.js | 48 +++++++++++++++++++ 15 files changed, 187 insertions(+), 65 deletions(-) create mode 100644 app/assets/javascripts/loginAlert.js create mode 100644 tests/javascripts/loginAlert.test.js diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js new file mode 100644 index 0000000000..67ed439ae3 --- /dev/null +++ b/app/assets/javascripts/loginAlert.js @@ -0,0 +1,35 @@ +(function (window) { + +// Set the target date (10 days before March 15th, 2024) + const targetDate = new Date("April 9, 2024 00:00:00").getTime(); + + // Function to update the countdown display + function updateCountdown() { + const now = new Date().getTime(); + const difference = targetDate - now; + + // Time calculations for days only + const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + + // Visibility logic + if (days < 0) { + // Hide if more than 10 days away OR if already past the date + document.getElementById("countdown-container").style.display = "none"; + } else { + // Show if 10 days or less remaining + document.getElementById("countdown-container").style.display = "block"; + document.getElementById("countdown").innerHTML = days + " days "; + } + + } + + // Expose the updateCountdown function to the outside world + window.updateCountdown = updateCountdown; + + // Initial display update + updateCountdown(); + + // Update the countdown every second (inside the IIFE) + setInterval(updateCountdown, 1000); + +})(window); diff --git a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss index addf9cc7aa..05cfab466d 100644 --- a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss +++ b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss @@ -552,3 +552,9 @@ details form { .edit-textbox-error-mt { margin-top: 1.5rem; } + +// Login page + +#countdown-container { + display: none; // Hide the countdown timer +} diff --git a/app/main/forms.py b/app/main/forms.py index c01ce8fcce..2e6655cc5f 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1781,12 +1781,16 @@ def __init__( None, [ # ('email', 'Email') if 'email' in available_template_types else None, - ("sms", "Start with a blank template") - if "sms" in available_template_types - else None, - ("copy-existing", "Copy an existing template") - if allow_adding_copy_of_template - else None, + ( + ("sms", "Start with a blank template") + if "sms" in available_template_types + else None + ), + ( + ("copy-existing", "Copy an existing template") + if allow_adding_copy_of_template + else None + ), ], ) ) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index 4f8c3b29ef..8cb28ba591 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -168,12 +168,14 @@ def api_callbacks(service_id): return render_template( "views/api/callbacks.html", - received_text_messages_callback=received_text_messages_callback["url"] - if received_text_messages_callback - else None, - delivery_status_callback=delivery_status_callback["url"] - if delivery_status_callback - else None, + received_text_messages_callback=( + received_text_messages_callback["url"] + if received_text_messages_callback + else None + ), + delivery_status_callback=( + delivery_status_callback["url"] if delivery_status_callback else None + ), ) @@ -262,9 +264,11 @@ def received_text_messages_callback(service_id): received_text_messages_callback = get_received_text_messages_callback() form = CallbackForm( - url=received_text_messages_callback.get("url") - if received_text_messages_callback - else "", + url=( + received_text_messages_callback.get("url") + if received_text_messages_callback + else "" + ), bearer_token=dummy_bearer_token if received_text_messages_callback else "", ) diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 4ab20f363d..1b80c659e2 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -122,16 +122,18 @@ def edit_user_permissions(service_id, user_id): form = form_class.from_user( user, service_id, - folder_permissions=None - if user.platform_admin - else [ - f["id"] - for f in current_service.all_template_folders - if user.has_template_folder_permission(f) - ], - all_template_folders=None - if user.platform_admin - else current_service.all_template_folders, + folder_permissions=( + None + if user.platform_admin + else [ + f["id"] + for f in current_service.all_template_folders + if user.has_template_folder_permission(f) + ] + ), + all_template_folders=( + None if user.platform_admin else current_service.all_template_folders + ), ) if form.validate_on_submit(): diff --git a/app/main/views/performance.py b/app/main/views/performance.py index 13445967b6..1d2a4d1bcf 100644 --- a/app/main/views/performance.py +++ b/app/main/views/performance.py @@ -34,8 +34,8 @@ def performance(): stats["average_percentage_under_10_seconds"] = mean( [row["percentage_under_10_seconds"] for row in stats["processing_time"]] or [0] ) - stats[ - "count_of_live_services_and_organizations" - ] = status_api_client.get_count_of_live_services_and_organizations() + stats["count_of_live_services_and_organizations"] = ( + status_api_client.get_count_of_live_services_and_organizations() + ) return render_template("views/performance.html", **stats) diff --git a/app/main/views/send.py b/app/main/views/send.py index 4332c7ddbe..6c786e3acb 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -52,12 +52,14 @@ def get_example_csv_fields(column_headers, use_example_as_example, submitted_fie def get_example_csv_rows(template, use_example_as_example=True, submitted_fields=False): return { - "email": ["test@example.com"] - if use_example_as_example - else [current_user.email_address], - "sms": ["12223334444"] - if use_example_as_example - else [current_user.mobile_number], + "email": ( + ["test@example.com"] + if use_example_as_example + else [current_user.email_address] + ), + "sms": ( + ["12223334444"] if use_example_as_example else [current_user.mobile_number] + ), }[template.template_type] + get_example_csv_fields( ( placeholder @@ -511,12 +513,14 @@ def _check_messages(service_id, template_id, upload_id, preview_row): template=template, max_initial_rows_shown=50, max_errors_shown=50, - guestlist=itertools.chain.from_iterable( - [user.name, user.mobile_number, user.email_address] - for user in Users(service_id) - ) - if current_service.trial_mode - else None, + guestlist=( + itertools.chain.from_iterable( + [user.name, user.mobile_number, user.email_address] + for user in Users(service_id) + ) + if current_service.trial_mode + else None + ), remaining_messages=remaining_messages, allow_international_sms=current_service.has_permission("international_sms"), ) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 1cac1410c8..628ac59e58 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -477,9 +477,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): current_service.id, reply_to_email_id=reply_to_email_id, email_address=form.email_address.data, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), ) return redirect(url_for(".service_email_reply_to", service_id=service_id)) try: @@ -499,9 +501,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): ".service_verify_reply_to_address", service_id=service_id, notification_id=notification_id, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), replace=reply_to_email_id, ) ) @@ -702,9 +706,11 @@ def service_edit_sms_sender(service_id, sms_sender_id): service_api_client.update_sms_sender( current_service.id, sms_sender_id=sms_sender_id, - sms_sender=sms_sender["sms_sender"] - if is_inbound_number - else form.sms_sender.data.replace("\r", ""), + sms_sender=( + sms_sender["sms_sender"] + if is_inbound_number + else form.sms_sender.data.replace("\r", "") + ), is_default=True if sms_sender["is_default"] else form.is_default.data, ) return redirect(url_for(".service_sms_senders", service_id=service_id)) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 4ee6551273..398a392743 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -13,8 +13,16 @@ {% block maincolumn_content %}
+
+
+

+ You have left to use login.gov to sign in +

+
+
+
+
- {% if again %}

You need to sign in again

{% if other_device %} diff --git a/gulpfile.js b/gulpfile.js index 6828bcaf19..79f9760352 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -123,6 +123,7 @@ const javascripts = () => { paths.src + 'javascripts/homepage.js', paths.src + 'javascripts/timeoutPopup.js', paths.src + 'javascripts/date.js', + paths.src + 'javascripts/loginAlert.js', paths.src + 'javascripts/main.js', ]) .pipe(plugins.prettyerror()) diff --git a/tests/app/main/views/test_accept_invite.py b/tests/app/main/views/test_accept_invite.py index 1deeca299f..900ff4bf5f 100644 --- a/tests/app/main/views/test_accept_invite.py +++ b/tests/app/main/views/test_accept_invite.py @@ -218,7 +218,7 @@ def test_if_existing_user_accepts_twice_they_redirect_to_sign_in( assert ( page.h1.string, - page.select("main p")[0].text.strip(), + page.select("main p")[1].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", @@ -332,7 +332,7 @@ def test_existing_user_of_service_get_redirected_to_signin( assert ( page.h1.string, - page.select("main p")[0].text.strip(), + page.select("main p")[1].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", @@ -421,7 +421,7 @@ def test_existing_signed_out_user_accept_invite_redirects_to_sign_in( assert mock_accept_invite.call_count == 1 assert ( page.h1.string, - page.select("main p")[0].text.strip(), + page.select("main p")[1].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index 9bdabf9253..c3d1281556 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -862,9 +862,9 @@ def test_should_show_page_if_prefilled_user_is_already_invited( mock_get_invites_for_service, platform_admin_user, ): - active_user_with_permission_to_other_service[ - "email_address" - ] = "user_1@testnotify.gsa.gov" + active_user_with_permission_to_other_service["email_address"] = ( + "user_1@testnotify.gsa.gov" + ) client_request.login(platform_admin_user) mocker.patch( "app.models.user.user_api_client.get_user", diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index fae020e589..0bf2fcb084 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -31,9 +31,11 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): "name": name, "id": folder_id or str(uuid.uuid4()), "parent_id": parent, - "users_with_permission": users_with_permission - if users_with_permission is not None - else [sample_uuid()], + "users_with_permission": ( + users_with_permission + if users_with_permission is not None + else [sample_uuid()] + ), } diff --git a/tests/conftest.py b/tests/conftest.py index 6c4f94b4f2..4c2ceeea97 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -904,9 +904,11 @@ def create_service_templates(service_id, number_of_templates=4): "{}_template_{}".format(template_type, template_number), template_type, "{} template {} content".format(template_type, template_number), - subject="{} template {} subject".format(template_type, template_number) - if template_type == "email" - else None, + subject=( + "{} template {} subject".format(template_type, template_number) + if template_type == "email" + else None + ), ) ) @@ -1101,9 +1103,9 @@ def active_user_with_permission_to_other_service( active_user_with_permission_to_two_services["permissions"].pop(SERVICE_ONE_ID) active_user_with_permission_to_two_services["services"].pop(0) active_user_with_permission_to_two_services["name"] = "Service Two User" - active_user_with_permission_to_two_services[ - "email_address" - ] = "service-two-user@test.gsa.gov" + active_user_with_permission_to_two_services["email_address"] = ( + "service-two-user@test.gsa.gov" + ) return active_user_with_permission_to_two_services diff --git a/tests/javascripts/loginAlert.test.js b/tests/javascripts/loginAlert.test.js new file mode 100644 index 0000000000..4bb0d3eaa5 --- /dev/null +++ b/tests/javascripts/loginAlert.test.js @@ -0,0 +1,48 @@ +beforeAll(() => { + jest.spyOn(global, 'setTimeout'); + const sessionTimerModule = require('../../app/assets/javascripts/loginAlert.js'); + window.GOVUK.modules.start(); +}); + +jest.useFakeTimers(); +const targetDate = new Date("March 5, 2024 00:00:00"); // Reference point + +test('Hides the countdown if more than 10 days away', () => { + jest.setSystemTime(targetDate.getTime() - 12 * 24 * 60 * 60 * 1000); // 12 days before + + window.updateCountdown(); // Update the countdown display + + expect(document.getElementById("countdown-container").style.display).toBe("none"); +}); + +test('Shows the countdown if 10 days or less away', () => { + jest.setSystemTime(targetDate.getTime() - 8 * 24 * 60 * 60 * 1000); + + window.updateCountdown(); + + expect(document.getElementById("countdown-container").style.display).toBe("block"); +}); + +test('Displays the correct number of days', () => { + jest.setSystemTime(targetDate.getTime() - 5 * 24 * 60 * 60 * 1000); + + window.updateCountdown(); + + expect(document.getElementById("countdown").textContent).toBe("5 days "); +}); + +test('Hides the countdown if the target date has passed', () => { + jest.setSystemTime(targetDate.getTime() + 2 * 24 * 60 * 60 * 1000); + + window.updateCountdown(); + + expect(document.getElementById("countdown-container").style.display).toBe("none"); +}); + +test('Displays "Countdown Complete!" when the countdown finishes', () => { + jest.setSystemTime(targetDate.getTime()); + + window.updateCountdown(); + + expect(document.getElementById("countdown").textContent).toBe("Countdown Complete!"); +}); From 507973f9ae52514353adeffbc81a9e6c1451be82 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Fri, 1 Mar 2024 09:34:25 -0500 Subject: [PATCH 05/27] Edited the test, updated content --- app/assets/javascripts/loginAlert.js | 2 +- app/templates/views/signin.html | 22 +++++++++++++--------- tests/javascripts/loginAlert.test.js | 22 +++++++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js index 67ed439ae3..1f3281788f 100644 --- a/app/assets/javascripts/loginAlert.js +++ b/app/assets/javascripts/loginAlert.js @@ -12,7 +12,7 @@ const days = Math.floor(difference / (1000 * 60 * 60 * 24)); // Visibility logic - if (days < 0) { + if (days < 0 || days > 10) { // Hide if more than 10 days away OR if already past the date document.getElementById("countdown-container").style.display = "none"; } else { diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 398a392743..8773fba245 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -13,10 +13,11 @@ {% block maincolumn_content %}
-
+
+

Login.gov is required by April 9, 2024

- You have left to use login.gov to sign in + You have left to use Login.gov to sign in

@@ -50,17 +51,20 @@

Sign in

{% endcall %}
-

Notify.gov is changing the Sign in experience to Login.gov on March x, 2024

+

Notify.gov is changing the sign-in experience to Login.gov effective
April 9, 2024

Why are we doing this?

    -
  • One single source for signing in: You can use login.gov for other sign in forms within the government
  • -
  • Security: It's really secure and trustworthy
  • -
  • Fast and easy: It's fast and easy
  • +
  • Enhanced security: Login.gov is really secure and trustworthy
  • +
  • One single source for signing in: You can use Login.gov for other services within the federal government
  • +
  • 2FA flexibility: Login.gov supports multiple methods for users to verify their identity.
  • +
+

What do I need to do?

+
    +
  • If you have a Login.gov account, start using it to sign in to Notify today.
  • +
  • If you don’t have a Login.gov account, you must create one by April 9, 2024 to continue to access Notify.
-

Don't have a login.gov account?

-

If you don't have an account already, sign up here:

- Create Login.gov account + Create Login.gov account
diff --git a/tests/javascripts/loginAlert.test.js b/tests/javascripts/loginAlert.test.js index 4bb0d3eaa5..895aa3647a 100644 --- a/tests/javascripts/loginAlert.test.js +++ b/tests/javascripts/loginAlert.test.js @@ -1,11 +1,23 @@ beforeAll(() => { jest.spyOn(global, 'setTimeout'); + + document.body.innerHTML = ` +
+
+

Login.gov is required by April 9, 2024

+

+ You have left to use Login.gov to sign in +

+
+
+ ` + const sessionTimerModule = require('../../app/assets/javascripts/loginAlert.js'); window.GOVUK.modules.start(); }); jest.useFakeTimers(); -const targetDate = new Date("March 5, 2024 00:00:00"); // Reference point +const targetDate = new Date("April 9, 2024 00:00:00"); // Reference point test('Hides the countdown if more than 10 days away', () => { jest.setSystemTime(targetDate.getTime() - 12 * 24 * 60 * 60 * 1000); // 12 days before @@ -38,11 +50,3 @@ test('Hides the countdown if the target date has passed', () => { expect(document.getElementById("countdown-container").style.display).toBe("none"); }); - -test('Displays "Countdown Complete!" when the countdown finishes', () => { - jest.setSystemTime(targetDate.getTime()); - - window.updateCountdown(); - - expect(document.getElementById("countdown").textContent).toBe("Countdown Complete!"); -}); From 81d89f464a9468baff0d6be69e3744e330dec4b1 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Mon, 4 Mar 2024 09:51:13 -0500 Subject: [PATCH 06/27] small responsive styling change --- app/templates/views/signin.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 8773fba245..1b8201275f 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -50,7 +50,7 @@

Sign in

{{ page_footer("Continue", secondary_link=password_reset_url, secondary_link_text="Forgot your password?") }} {% endcall %}
-
+

Notify.gov is changing the sign-in experience to Login.gov effective
April 9, 2024

Why are we doing this?

    From 0bf289e23ddcd8285199ce0d025b0858938f719f Mon Sep 17 00:00:00 2001 From: Beverly Nguyen Date: Wed, 6 Mar 2024 11:49:04 -0800 Subject: [PATCH 07/27] removed macro and added footer.html --- app/templates/admin_template.html | 4 +- .../new/components/footer/footer.html | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 app/templates/new/components/footer/footer.html diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index 6b33fed058..1352d8a758 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -175,7 +175,7 @@ {% endblock %} {% block footer %} - + {% if current_service and current_service.research_mode %} {% set meta_suffix = 'Built by the Technology Transformation Servicesresearch mode' %} {% else %} @@ -249,7 +249,7 @@ "html": meta_suffix } }) }} - + {% if current_user.is_authenticated %} {% block sessionUserWarning %} diff --git a/app/templates/new/components/footer/footer.html b/app/templates/new/components/footer/footer.html new file mode 100644 index 0000000000..9360782506 --- /dev/null +++ b/app/templates/new/components/footer/footer.html @@ -0,0 +1,107 @@ +
    + {# #} + +
    + +
    +
    +
    + +
    +

    beta.notify.gov

    +

    An official website of the General Services Administration

    +
    +
    +
    + +
    +
    +
    + Looking for U.S. government information and services? +
    + Visit USA.gov +
    +
    +
    From 87b47d94df25431d3970e43fefb35815dceee4df Mon Sep 17 00:00:00 2001 From: Beverly Nguyen Date: Wed, 6 Mar 2024 13:04:41 -0800 Subject: [PATCH 08/27] moved usa-identifier to footer tag --- .../new/components/footer/footer.html | 111 +++++++++--------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/app/templates/new/components/footer/footer.html b/app/templates/new/components/footer/footer.html index 9360782506..fa22b6a882 100644 --- a/app/templates/new/components/footer/footer.html +++ b/app/templates/new/components/footer/footer.html @@ -48,60 +48,59 @@

    {{ params.meta.visuallyHiddenTitle | default("Support li

- - -
-
-
- -
-

beta.notify.gov

-

An official website of the General Services Administration

-
-
-
- -
-
-
- Looking for U.S. government information and services? +
+
+
+ +
+

beta.notify.gov

+

An official website of the General Services Administration

+
- Visit USA.gov -
-
-
+ + +
+
+
+ Looking for U.S. government information and services? +
+ Visit USA.gov +
+
+
+ From 6a2f54367c8aef8a7c9720825fd5e8a35013c225 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Thu, 7 Mar 2024 16:42:57 -0500 Subject: [PATCH 09/27] Updated logo and og:image --- app/assets/error_pages/5xx.html | 4 ++-- app/assets/images/notify-logo-dark.svg | 17 +++++++++++++++++ app/assets/images/notify-logo.svg | 17 +++++++++++++++++ app/assets/images/notify-og-image.png | Bin 0 -> 52879 bytes .../sass/uswds/_uswds-theme-custom-styles.scss | 14 ++++++++++---- app/templates/admin_template.html | 2 +- .../components/components/header/template.njk | 17 ++++++++--------- app/templates/main_template.html | 2 +- 8 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 app/assets/images/notify-logo-dark.svg create mode 100644 app/assets/images/notify-logo.svg create mode 100644 app/assets/images/notify-og-image.png diff --git a/app/assets/error_pages/5xx.html b/app/assets/error_pages/5xx.html index 48cbe9e618..d9d58530fc 100644 --- a/app/assets/error_pages/5xx.html +++ b/app/assets/error_pages/5xx.html @@ -22,7 +22,7 @@ - + @@ -107,4 +107,4 @@

Support links

- \ No newline at end of file + diff --git a/app/assets/images/notify-logo-dark.svg b/app/assets/images/notify-logo-dark.svg new file mode 100644 index 0000000000..798ce99d92 --- /dev/null +++ b/app/assets/images/notify-logo-dark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/notify-logo.svg b/app/assets/images/notify-logo.svg new file mode 100644 index 0000000000..3afb2dd924 --- /dev/null +++ b/app/assets/images/notify-logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/notify-og-image.png b/app/assets/images/notify-og-image.png new file mode 100644 index 0000000000000000000000000000000000000000..9ca227562627ec450b92719e584558866457c0a1 GIT binary patch literal 52879 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

xlI z+9kJ0*xi}H2oi9-fU5c9TNHj3|>_SlXFI zxCrzUc>323|Exn++L6+I*EF@oFz0URxFPiY+H#tek@<(lYN5+|NyCry4NfpOt6W1n zbh_k!*2mYOl0|Nr`3*!x+nLEv?ZotLf7Su1a6vmLRvl@5?>$E8M~e4dPHXKI&m3NSzVsJ~xJ^QMqPUs4(dNqS zV!B~Fck5|egkCC{%oj`nUd>n9g^hjLYW zOqyiblmuheO??i_rS1kf^}a5>GP*|jdN}t*Hryq37y=X$eSJX{8GLVE#Ot(fX-4#g z9#7D;6M|EmRuDOPv3qU(N%5^8p~|nx8r{hKKM%^&=4OE`_-jb2%{z|(yg1?kA;2Pgx78)E4{>5%{C2Vg*hUCJfC&O+!D?V$B`5*$#nYmEL zVp@7_Zk`jK!$4c+80goISi|Kto5Gt!PK=l%o2D>yuc*kNv98P@j|-d6KY01lA@lg7 z?rI8je#o{bQ!jOfIHcXmt&Q+LS-fvNuIs6)Fp0Md2@dx+b-){lEq(H1zzHkg;D-jpDj0E+Si1 zhzL3F87U#M!IISuRON9#A9;ZIug8n_c<1E7bLz z0Ktm4z&;N%E2;8jvT+ zgwrtlLkhKNfRcPpmBr&5xdHz|E&J=$VKabFO4wZghjLhk{MxQJ^dHYXA?O0VFC{hv zR%86$B&xF=Z518~9{j3*%Wtck1v-D?I=|(oe4X}mQ=*zo+KGWB{h!B(q{>S-xEn~D zd~apxaT%`*8Ow}Vr}dfkvftiPWox+4l!FCF{MKZbNkvat6NOXHP7@&Pd5tzAkv@eg zoPzsR?0VuA2kj($k&wv|v#re9Q<{CA@M-Rx@V9mD$@Vy~|7$=pjrJwV_TP&yIchnb zY|JKR8NVZEcOT#xh0|L<4DS!QR3Ysszw`enTp3$=d+cIO1+*;8pF2X7N?T2hXNIkC zkdU2^1c4G{?NKWe6j%>yBSKKF0I&yozhK{Xdzzt^ajlGZtbzZNuN9hWHLUY&q`KEm zQ8H3(6SrcqOT+s~DT68VsY^)@P?CE6Qk(X+hDu&jZ0=h{tKZ(U+dds)=ErYy|3X~n zpVctH915!UDC=+0H`m%ze0#K0+wfq!j~9^ZWLXCLd<|6~YgERFhXe0Bh-$DkL}|-g zDM?&Oh3v2;JuA?Y66mk^f;4DXfVn+SaZhJnxpFTA@u#@tr$-TE28STU$4G3kT}DW2IjsK0y5;=wRpkNy5FsfLJ4;Z3Rb%?jThL5wnHk zuUG#~SkmNmfr&xvmEseA5WTC9RMAbw=7sIQI&y)rX;b~bXThA&QMDQC#ftjg$I(Y@ z(rg8U`-7kYdxrPwcr#ZssPlgJ0}yCp`q^S7ZNUIes&RaB-q}eJqa9h9Fs>!#H8pc= z>TJWrVRm3W<&YizLZc>R`0zAQ&KL5YQ173X|1b!1_C0+OrKSNoK1d0xD_s9G6I(`@ zsRowFE!21DXWPA*1Ovt|o7Gj}-2$i1#{6GFgED;D32m!fS+VdTnlJ)TX-NfO|F8V` ztE_m(3Y<`kD-=+h_pL`hA3ICly#b%`EowF1w7lr2vOL<)s%}$Es`ORLXI9O`$@W~0 zD`*h7>WRYu`ALuih7x)#Fo{i#m@3mb_GRsdRshZwS%rQN5>-Z#br+-JMBZAsibgWZ z#BF+)=L7^7o33Iu&r&F@bkQa7u{@VQGC?H5FzqYSYV7YsTF<_$1Ur51DE2P)qdhdC zPG2>xTFVnsreAVVo99pH*sKOmo<1wDKkgE-72?f3@Ob~bTb5-N9d9)ExEoZ?ZsH0~9j`gM-5LAqbE=5JV@_#aEamb;XS*Os&m*AnZ zKP_pbs%!z zZX>(#B?Ir%4xYU88^_i@=(d%M(Sts`;s@og)JHPyu&1VZ1195M%IakZo(LcNV#)KL z`D69(EH>qxAFlpW*xrsfOYh_Ep*$hC2yeT`JXE}p>UGm(;$dz?mYr~T=k5_r;Bicl zn>nxZFA$4q?#;CqOA^b^|mgjwi2hrS#54kKY>m3@a7BJ^ybC^yd29H!;7+%Q*(bO-E2ORW}j=?jkId9`(V#ybG+=<6D$21ZBh=YDP>cf_#OvO-@6W8nL zvSEFOnYx8eJL*>%{Y&e0VfH33^76Sw3M zu3tz&=S0(>BcjSYpGsV`X0L%Fg_K^X0%Y6K?Z}claDK*Gfzn43VlmCm6&X&GdoCOBM>QSUFBs< zE>P|TzjJjZL8LY+<^y|5Ie{W1|)Qz>K|T2`D!6>lK&;7D>a#eg2;xVHl1e(@;p|-tR=jGw|!j`67}Y8 zJ`tD}R-e>cOOAafXM45P#w1TiOlBFX)VQ)+`a&=ecYXX%+|Qj&Ozk{E#8LqtMy@k(P-1-b0%`K@QXH};L1qX{#6ltH2T6~X{RwX zu!tz!ZzhcioarhZG+3S}8ASe>JD})hxv$D6T&xH8K4UM&!W2i`d7Fei`ChtGMI;@Z z54}^`29Zo@0glLv?urING9a{e?AfGR0Sw*{8}fWlIC8Gn7_D=t?iPOV`(RnSdm;#c z27y%QulX5%l?AE{E}+%odbWumwquuYz?E8}FFw%^X>xs#YF}TlnDsiX;dt99zDRPo zYTE{SzD94^8sq1B`k81VUl>toX^~bc_EKqIwC&$`sS(&Gy~OG=3J|6cO93^k6z za;KC7#U<&xUdOko5OF`s`uD~@k?y^p)by;uY+nlMro6=n*rVG0ac)f)%1b*PlUDj^ z!8oB2lL^jY4Cm)?uNwa4evj2|{>yf86KAw%SXu9O$ zL<{II?@S~+)aVlc;oR)c-S1{@ENs3}MQ{tcY4JJShW8HXf>fT(lGOA)7mUak{&MR@ zir_Lqo<+{HlgBt)Wa)y<=7YJtlX*6|ekUEyg59Dg0`|=b9Vqla4F)zXHf;;9xmcjq zIA@&I-8i1$bmyb*^A{6-jTomFJ;r3eVCm=EtC}-zHS+}x)h#Bn9^xHUbD3sHM~N@T zk0!m80fdCO`a?!!&?#kVg^Wz4$e$)hiu)yAc4&&GJAU{=MD8(?TlEq?x zi#1Wtv%H%yu%u{IY#iw!M&@^-%&@D{3XYTp>|{rFs#|Wrg0Lu(=GJtKIJPC*#03LC;6bCdY`IlEy-U` zx1_F@6KGa!^>FSNq%i-5($WU!u#)l_kd>>!k`al{%(_53QU3zoE&Vj=e5a)61vP_z zZmYwqerB!rA>@e{V=ZGX9k$0&8CQw?tR{hqHg+PP za8G{!3JOev*J=JYMZB!NX+IXDvzR`pVuFs7I-ArlKl?&^21J;$X+!C( zcN5m-;;KBf?ywxI&ZnuPK?SUAMx*6nj(T={FOv=&fH^ZqMSd32zox2-YRg{YtT@pe z@qPwz*qC~AW5nop#W#K>!G^~VX-Ei;JxdOFt8I|}t+IGmV37Q$HVjamq)$}N%-{m4 z@NKmMR+ut{>~qKNoF9fd?uZnD zWxmOATfpv)T|}((p9l9KqE~aK+TG_9lwwA@bv?DpZkz)ka>lhqLG0+(m%EEY^&Xy1 zz()NbTAAE78@aW%zx$2-==@?F-{^1@tqH#pc!|JhI*27y@hw!@txljt%h3!-yVhkx z$7Kh9Sy)W@MV?tGdHKSvs|e}i8h}fv>}xFy*%lU6P9cIs}bxO z8{`K0sjM8|PSl@fQC}LTx++v$@Qponnmfm|CnP3Ij25GCD2!|M&h?(oH`1Lp)rn9e zk`tQtmrTT&U2r`Ih=cE?wPsfs+sxBbyc@`&Tkz~*KCT}HVidV>9dmjwzT_pa`C!0 z?z~+`A-ZxSA>_k>kXG#pkHkw2Luc3OQiZH*v)M3~FP@=^hBjmnc>uf zXX?crYV$5@y^QTTp7mT#BdSW3Z^2=^zzD3;6%W)HB;jKxm?WN{lvy3I*4NbW^7wVW z4M0Fb#t$4=N%Zp4u?Ll}0_%M{C!$-6>Olo>8hWS@VI zP&6V!s|B!5B!A=N`7R!yNGYBkcMSY>$6^q$E{HxRp4*?W_GCBCs34oo9oglD=Wv&p5xL$*U2`2UjhAE?`ZQK0{K0OkFk z(oua}5z{jIXnH+2jpeV3ZMIqu zo&^YvoxZJ-GP#6fIuJouMRI>vF@nWW@n?9=$*lVv-uB`Z)>H4z3z_>%_J4f;iwj-> zwXv}|m1iT}PUj+qk|$5Fe$c~n{h#>Igc)q8(Y&`aYimCwgr#=8GsO=5SRFh)Jt?{w z6{c|tAzdbB%nqe(Ry#}S(SoNiJU91hkAz1 zL+-jtl5ki*Zw1qTP{@0NzEJb*kyp~cJOx3i!e{?eJ)DhJ$5e;4mG|bA{|cI4At;R$ zF*UR>Q%NWOpYJ8H1qVDyd4MLndXw;fN^yWv@s9@P#pP}P;a?%%!tzw4t_k9mU3fSh z0{RV^q>|-(Z_yhw!uq7p9$ukjmGki z7aFAt`VWDSd|{*Yeiq}ZG3v?;KA880!+GtO$jtBG34l9g9)PN^`+om^bFxw#k`yD@ zi6;}%yIkguNpWu5)6LBj5RKkzA6LcRdPs65Tf zeVe0V3mD6~cRja0HI)TK7WXy*WOcZ2s@;g$DV<-PX}el<8^BB7EBPRXKw!Q((v@Ep?*@8np?FedJe)TrcV-Hpwu540pk7J2RDKw2Wbv%Xs7GoVRgvF#Y4}6R(B~ z1|{(QJ27EisH1f-NXp&jORuT-1nh~za?XOYdPaLn%2Svxpp z47*ETM>s0LMk@MuH#B|KK*B>x8$amh!>~CzekjEe?^VM|_g8NVtVGB}vfpF*O zaZmlTe(i;bq>Gao_fRh+GbO%G?)GJIk=c|;dkYRy4sh!o_&D(T232oOodep>_-E{W z!tz-O`v7-oVsq7rvv})XW%%;Hmi+!Tqtwf6v;abQUxEE{ z>Cl(5h<`#U^OdT_(w@YCpV({I!DD~7_TA+?9EWp-4C6Q^io<*CCoaXtMr%R0JE^9> z4-N_rSqH2L=>aw0PHKEIe%4wL97o+Gy#$cnVA9qR$%S8?Y55k{k#L6(A-f!!4aZ2j4mUm-AR1zz>izSQ0KrCqPPx1Ms0Sy2kOLV|@}&Z#;MdUr)4#gn zjIw+XQF;)MeON@ai`>Aa78Y>urJ0V_9xxʛy~>@mJ&A}P!*p8KU+dY4R(+@NN< zve%tX?>aVSR%-s`6ozB`&>6n2w9E7fRDqP;AS@k7l$uHLItLtivm+|28C!Y9yW)Ba z&kuUpl8yH9BB$~=gVm6yl_j&fNA3$q3(RGK#6@9K$8>IZd zs>i z_qWcZvC=z7FPhBHgh62W|4^u9N$Ot94B zhdRb5f!qNwXB`8VEmrtg3U)*l$GDI3zM^#-ck4OLnpOuSmpnz>EyYfE-;(O=NINCE zV;Z9{>%T3mF;ltqX;|^o-6c*OAuA*vmO>nOAC~BtqrgHdyP$am$VdH?_bEO?6EWL! zc9K)g>xq?r{B~>MPegZ$Qn9HLhez+@3-Gm(O+uX)tU?-J8UtFpxt3J7J-vcZK9&P zZ#7ZP6BxXQWuW3<6|o6BFG0y`!O@o95s+VYJ6K1n>7~185VuQqw(sTnhyfH#2P2^gD-!4CQR3*YU%ZfBLm6zGE|&z@#Xgp_`_*2b<$#& zGlHA>G}hu~(-(g0T{F^`7OWGvnzTU) z`;fNZgfYC&0Mp*%$wb^YeaDR>7NjESUT`*?HpLg(2t0r*5LSYchajNVn_CT*3XKJ~ zMVH)R?QEKoBnDQeg;_h*Zgb8G`&{<3js<3{AUy&A?*na+9(}!~w|g))jl@?=`V+X> zqA#)mm{3dnsJsr&LRfr|@4WmDUE2k8129AUK(Gh%Kt67n)&gae$1jjWP#^Ft*w!=n zGp_-TRO4;{QA}s9)TM$=R#;F#7O7g4w5zWczu!1P3I9EmPQh4b_-S3|=Nf$(@UIIN zxooJbeh^w9skX#M*}?O%_PLiw7S1|;*?u~S<1b}1;GV6;Gv9LQq<<5E8Y<6#edGeu z8U?V1o9FYfM;(03qr(kOnJT5AWIawdm@DGQNdnSe;noKN`l@?M6Ix+T%<3}*P7dg! zB|c7YA4O&gSkCktKo>^&YT?d@D(lHLlMY5y9WS?7k)pG-j>Q{i(T6>4U_de$T-llH zEtYbx4B@vLHj>1;93@N*QjX8zg_zX>q}48D&<5SOi)DTEJC+J`VLKF8wUJP*Le9(iy$w}YL|K^maXsU$gwN`v~ccDOts_4JaX#3+#3}GgZq$$?1wa^GnCcZX^gRKew^jFN3r} zfAzujct8&Hc<6e|!$kY#Fl&&Gf$3!q{th}>qVmxdC@EMIg6~|#k+PfEh@Subx{+1a zY!OB=rEb*vnBEkpOB`+kvV>TM$n%*RzNu-f8ZLF-zw)h%Lo;!e3m>W&&SVP_ zXT;;XQdZ31QtbuV^kZgP6LYqlX!Jt-fuuiQNrtClxYG2NrOu~VulZ`xxe+2PYmc3a zZO5@$mu9#6@gWX$xUL04G|9?}!K(FSXwG0o3O-e6JkO&_5`2N(Ep)g%gnM-3LFy<0 zH!H|Nc!|I*l|g1u2%K3d_dYwnyck=uK74dp534*xO3xKG?;_PG^)z6@p`?((Ss-Hf z0Mn93dX6PK&u&h0I`Od*e7tFNmW7;MEV`J1Lr;XHFVF5zukQZU;xDW`$~Dy4#IB`z z{ru|&5<0VLUPkbfn_NWC=`LecKTQ)PKp@&UR~PuyLV_Ul6_ZKwerp~4=)81b`p?0( zFlj%xcgbyHmZOt2ZSdu@9^QcNyZhN6zdiH0ZZVETabpjL6x&SA!}_lk4gI=YuHTu2 zAAOD^D7^_exMrYm10w)rqGqoyI z+T4j5h0OjB^Lm@tb=vtajz!>y)nJLx18R0N3YAzUfNL5QPP@Ob7+}-A)DMxVp0E&I zyAS&kLIvY<{El10-Q9|C4989ccAb9*j*XxcgLDpkoGAd#vtW`^y%Y-tR&oFd-zPnZ zhohNsckvwG+#r=n1tV)Ykdbl?YY3^vh`@I-{1ewH zTJjQmn$9t8@$aa%`$VKl};c^p7SZ)9*i!eYK0kVvP9_I_g&nqT{9| z&-?O<7)xTP?#0br{^40wZq0|=jr>}O@P*=TplKV6v3ozEYDs**cN^q~bg^j-se@P9 z!p#UgZw7B3;SwKa`$H@lnI*Rl(!I-e6b;|ZlR!X?4*W!)oMyqZgoA6<@&anzZ*_jG%5SCSqkVUOm3b9=gGbN|q-(bpD! zma;1fcJOe_hIrl4sPt+Mf-X+nn*0Mgs%xp zA2v&*zvb3l&(gw%i!BKv$teVy_T-AkZAf-BoG1t&71RMUc<(`$*;tT%MdHrM>>_+I zr{PGe$YCob5su9*PFcW?hlbZZdUe0v>0pgfatHlxyP2SjeslNId8gX1M^YhuXg#Fn zaHW&(jIcx)zDs`5t8FP1Uc8gG3mmtpQ#W@Shwbr+@5)j?Tv#e*oW^O)E+-8mchJ*sZ3)Q^z-BIeWkrH?SZ9J)p&hYJikPPfU%OF)5dM z3oxw59Q{u2yUyk#?628JbzbZ9@8MpT&4&X-c#+dGm)_%>lmI#a*3S%Jx`u&Y91>EK zj?BstmBzR#%oLnMm570fx`UHZB0L0-b{NJlDCzbB9wHE z0=q=~;+tdg0>a?aLigZfM*z7^6fJ9b{MaB|?*1DY*~j>3@3HUv;Ve&H=svkOd2{cc zKoYIu>ih$8fw*#1WK8@17mf)+)b*GgIt!9tPv*F0)Z_&)m?`A)$<~EeVJuCBM9(a8 z78(6l3WK@8Lg@UV5WVY0DbLUvM?Yux?uylVoI5?T;`)2ke4+5WEdFjvPqy*olH%Xl z#c{d{YG7zvXxM2XbOg}gF4;}yeBWqCfKll_!Ov&Rc`EB>rn%?qYyYlK{X+RA_4;nA^0@9nPo+gF>@@y#rr z*OkPU*iX&iGg`GHiVLDQHVD;plcF~W$D#*l`dEAWy1TE_v!IY14_)?p_8vi=sus&u z){?fvM%2eS8?j%Q=&u#OIQyFs(s(z;6=7*<*#>j9ezPM~&C7JZF`SZuBH&U|^yoXp zMT5P=?V>H>pp8uMz0H6;85j>l$b^Ki+ z>&2BTcJnRo9wsA|)gHU(Ryn+QQ(ak=fD+KT^GkI%R&C9<4nF_DHXEt@u3h6Twq8IE zqy`fBZFY{mF}7l7^0hD4iwymMf-s{)rMSQ(T;su97v1u)OGx&3&diw9DnwEy0>$yzSWh6D+1px+1g^<8#$iqn*UQ zCKDbk(tLR(>N{2uP8-PGIqA@@I$Xah`$A2Cm{rGDPza9ONA+lEr1inZWL4vj%{Nw7h2YwybiWHf+)ea8 z>)9!nn%EA*-!;eLQ4yA$tYY5A@RO}+dSyq=uEJ{n=AaJ;9rKYDdWW*byc-ORjNdo= zoCi+zzMmz^T0Cy(l?%=eC&JUL4T9RQ{))XU*+WNF;Oy-n!QERNE#hGiUTp@GU#=dx z{jQe9Y*Hvl!6T@{nne70SCPhWsCwEJM4NAy-Bwn5X!^iyx^PW~pUf^txluHmzL6O= za~wIvr42df$Gh>4tQY=JsA0Lqh{9GGZ&9+t16X6#=;gAh!Tk_^q$-1tr#eZi#&kwq zB6oLwetuLjk?hmH#4)um?Lm}%i`9Q)?_`VB7+Mv=I4Dm)WEK|>6i#sz1lD<+4YS>8 zDE=`OPRQ$9WHseG$63DiPRwfqp5$vB700_a^?piO{ISqETQ(GYTiTa z>=@Z=zV|@*(!)o(!cF1QyK1=Q=j4vMwS(-B1;gEoxtC8G)Xo(fHNUQzG}Lx07?(yF zbj0>fHvK4cj{B6?RAj)1n47yAKrbELLyvSMSM|tV4Oy-o(pJ>|-s(0N;YC&D$@PZN zWoUi#joIFVv0b7m+v1mhn1+|W;}y=HJT7uSug^NEpG!Ti(N+QNr|h+yk`q*M65FmA9@VKq)7TaAV`sI$VNqp&JC zAWH*9yFDhf#m5-1K^SfGX;}J`44;SS{Tvgk(6NkV?X2x)21M@lOv`|=6JMEo8?PlP zESm5hd}XO_3TkFemdFlh7Uvx@@jz*vN5F3vHkA#WFfuVvzo%oT_3oiEY9%Gm_UZ{L zG(S!uL`PuNE`JYXKBfyA86q6qFy#w~<2SL1g{cDfuFIZ`^8`xvRr@{97W$yFkI=%k!O?Z@=6M;?VH7OyLc(DI9n zh36Fnq3_lB)cE(2kYU@g!=q_eR zdRWQlIgQin^1<|RkzcB+Ia4r&pvp{6emBoyO;P68yH~7U!RBh%iQie%rrjj!!FYuI z?XIiL4VsyPS6fDANf7Fqzy34w;RZv#m5vRmbY;l2_|@xPw>$7Z-Nol~Ssx{|xn}mB zrVTOFR~)Y;;1T-eSJM6G6ovk8dHE=GQNL+hECw<8V}w$gEo}8}tR)(^*E4_TMzT$F zj{ZiW8b@|#ZX!qRk>ibIrcz}^LQJzeekBJR3%h0}QZw11o6GL9!OPTqXsNx(b>~{_ zmpGv+r^XuXDe)7cj1(lJVoM-ce&PWl7Wbc^+h+VoW8B^f8x9hq*&?3)jo5ZJjj%RbSTazr}W@+Q`ZqQ-mQi+Mb>>&@&~v z8PztiIJ}wu@ViolH`Spjm2#YL(|#!WD`9DqD^(XCm#3t8q`u3JgW0dddAE5t)j>=G zYBN12XT?F;U_Dmr{MI?;le_IfzK5oJMpWlbZeK_wxHd|4^t9-D&WdB93|P;NpU8wJ z>p5&%!hl9&u})=@Q{R?Lf>Z1|tYXZ$4y0W!pfYLnT9ErD>0WjE5xWlA{9XDEpG}+q z3i&YV)vjtxnizmxn5|rXseMxV>bclZr*Yn+;>X>C-|nDD;^a(qm9J^=)g=tmB3D4_ z+(As9VOA_N!-sQ*_ZDowYpvW%eoNhH8j71f4%@^Tr(!=D&my$whO6`qauWW~MLC$- zNw|aV{?U`NKsxP&+$^iFZ~Fg?jJM3r?{8FYw6we%A(}l;-Vl;Cvl1dIwo)EU{pp(S z6HFwN?XR`4f30ZY{Jgq9WVEZG>qYTGw!bz50jtMB`udY$jK#H~_W2(R`J-3(UZ``jDnZ&BF?~+sfdbf(jC4R>S%Qm_z)NnT0aw`FTlTbT%q zgKTA$YBLviQ??F#9=aJ#NJwU(e>;VJfOxZ=R?denD!DP883M$Nb7$78dmAbNY)_l# zN|q2@`YrK&hrSLL%IOLjLfrfeBs$1<BPfn#6 zP?%?{23C{vRg5_UUxzmc&oI;Fpa5ibQor^(aQ=7+Q(n5%e zvVF9bSBg{WobnQ6FpRZp%R9Eg)NA+L{)pcEyQ2X)#^n8UMJ)U?^1| z`j&+Yx@qr02c5|dg_mNDKXi#kY5ZH$v!GgC^XIgkCGNbQA7PqPsl^EYU%|A1$+W@f z6C47|rFjZs2OSr(tm170wFm>K`m)_j^kHtXg7;X(M|$-FV%uOyhNqjA1J%s@TuTfk zT()66{!oi5N1FU%M1=|W&R)KZJYT$$K8!}w*g$(f|9dU>84uruyK!uW=bM6JH&&15 zfYhbly|UhfEl=s#V^K&BCnTj()P%-wXY}+6sQH+9T!!}Oqm*$i0EUPdr3uIvixDpT{FD95gcW0gX+sMgPVas-?8 zCoSp-8e!C#WRafl+GFH9(s+`g3YMgSn6kh}Z%X>r)coY-hovJ8(E7*$n{U?AEW;Bl zS$%>hcf4NJ^z*)Rk+_R%fey4_R#fP}%{bn-crM<9zqvRVB>kQLP?dy1YqCJp`*TIu zn2vFD2ducTa?AmP;0vZ3A5ZeDtzbISAFGNApqlt1gC9~;r z0Bm<4?@gF~2Mpxgx^%amx=#HwI=5l(jR5J>LN!R{U}L*xEd9wdeAMO_f#AX`>m!SH zVZA1zOG;Bi2>$#@sWo|YO5X#WhTpX2$H0xqGg0%)7S;7?U)V07pA9z$ws|=K44~&R zpRKEwp))7q*K&teXxJEe9n~!+H#HAIm%a4$V<~CMZdyr7MCfjfFg0<3+83*q6nX|C ztHR_X&g7x_JKSQMJAPL$Y64gNR(lTgEKc8=c}T9QJlq7sc@X#uW%(koItvOk#u-}+ zKGo;&Dd8luxwXYI`@WRLf=)+t&eUerW>d*5ou>d|JE}#!&UveB`bm}XPTj4lDh|`^ zb0uxw5|3+UKijeIi{j(nefQ~Z^~36Q1%2rYDczfuGLQ3EqA zXv`JY*fssgk9OvqqXDp~O0OLysD5LM1LiA7k2R$#MiGJCb1o~>pz%K!gA#0SsvsY zdLl3l<8jn>6ip~IQ4Qwi02$|?^|qRZxZR(U(>Av+dIPK&!4n?s+S}(T@`bCs?NbXO zRHWU)_%F^OrDX?BFBn>WvMCQig#pcyox5T?h7=zp}X*^9qY&pN*(43~f0wF4(}F4a{9x zC}4{3M-fKx?A=n;)U=x=@?&q45hp<;d{18#6V6CDYd77Q{>@H;G9JvY7SSDJ5(~=L zNW-uD`t_7IC71~O@!YO*K#>+Q&mY?ov2KIPU6tlgZ>SF;e( zvVXfTzW@Z~2N0AAId4KX+OzqYH}ML_OT9#g^`(%%ri~Oa;)aU6HMfY!>0)mk(A1FG z8&+2xRl%(SDhURXi-WJQ(?&7_PtRm&Qt3B3wmzYYAm$p(G>9iV?6vM!endSd{&Fuc z@7&D=LIhJ4Sn+?8U<nIqIL$r`dg(YPx6HnMO*L${z&G7qQk z-1QNU$QWE=LBkrc-F4I-P(mVw!h{20f~dhZO7nF<#uPwCu0nqq?ZLf#_f>(uc>lva zK8LvQN_0teytcSS4?XX4Bw4QU4uy>{Q0!7*N%mI((CE4V&{hL{pr-3@E2f5qnx=sY z!72mZwt#bQN$AzyZ$QhbGJdp2+yp!=A;;J93Xq3dmY4nY#1Vs0VaLZgsNOvqO&`8; zeXft?Uf#W5I|NUD1{UC)F^OTBV8YWNKp2ye8uwebIHmL4Z z{&I)jjKp?v(jPf)KBwP>eQ4V}u=FF_Fi98;kyrHfaff8TenAyqc{$MGkHO4(0Y4`4 zNBERTs0Kr!KgvmwRr?CUqvXfc#m7?q6UXAb9}?VwW-uAj_6ap^WTCP&Q+7mqlro6f zK{Jh*SDMN)PQN*#X5;{)RDjQ6f!>My(VF4cx@cPu9a1u1)$JrqcMB_YciVYI*8rt! z-)QmKLN?i5OZKe0tDdW_|2P^EviMzE zGvF0gW_QhAPcEzGj~!j2HLK%hy<(c4Fjwq+jc)TKr)5+3rwgx_(>g{ML&!+o{U zWUR^7(*M215G=Kb~yluUi{hjsH3BTv320;pwO ze%+7vu8%00iiNM;jM47AJ<&;`#`S5ez9;h&tR z6IFOK9QT(-76-HOVV~As;6)jw6ldMl)CsGmom^Se=56*6dH=EV*fc!dAT26E$dvr- zu~A<0AL@ODf!}ed(lyVoV;2p`q%T2^~)!B0Q)|Y<72}~w^~+c=rN-dhi09* zs>y7OAj`dAc$wSN7vyc!=6ZBj6%KR_^_#{$8mK4*5~ zDIZw+99k*K74E!K=waFV^zYH%G75VeiL8qsp6za>YkcjR-?3MY&tzUy?5HaGefb$k z^ujlg4W;>s+{oki=RqC)TTh_tyO-Hd`Fo9b;<`HaoZb@xeZ>ciOrE_J=NDZmc=wZ= zB6$H54h}w+`rg|@19y0y&7LNoKPF)9S(~lxv$MA_7`f?%8m|FX8o6|Z!lz7?{jcFA^dj=kW^Si>X{3tGURP@sJpNrs0`5Ef~y zUMmLrq%4?<^f?i57Vn=i(0aO9kc_1N}goqn&zrFSDqfoGQ0$!WhSaW>*2sJ)G6Th^a z;~3H!O6?Kvzv!oW4ZpAbZ`1`~)TdxB_W~md{XH=(51I>RoVF)NX{EOrw@62tJoouL zl63?nzp)4Yfv!$NgFc>Y&l#dZjjP3=$~TJJhF>p{rYV28I`K%`Oq9E^I0t&L7sF->`epBzHnkxZfq{yKK0cRn8pTR6)iiN-?`0G)Kz@Q>&(ee0bj5e$<;KrNLl!P6c+s0>CSY;g7~5B@NsL6 zypB5+l;$tX-@*0c*2Sqwp#1EBZtgG(hj=TJ6#83KEvSw*zSH_WY&-;H{Isj7(lPsH zL0x4-2zj6YXS9PT7C z@S(TPh*Jqn>54+r(%Qvs3gl9fQYZdwz`9uh) zI6TPpQBfyNZ^JJ&Ro!p5MSizpd!dngB(>*VGbmh@NFY;;K{ugI4c}lBn>FfFw_X@v7#_ z`eKOyErwGEt4p25W)6KPM?RwVsW;$|$=h78L-JG42IHT_`70AA2XGyZhi>XCQcZ6o zJcu|X(}7z@g}N7#*%nfd1f*24 zYnyj!?WSI(PJ;Wdt=Xd(TLqoT&3Q{{UR?2x%NgU;XFYITE>_{sNqD!5|Znof>2tvQ1Cu~2<|qQ`^3m0m^@RoX zpp^Qp4N+z=jHvhg9pbjWZgi*FnTB8ewU(9T5v6CVeGQlBYTvC;J6YNQM^;QyiE7TM zQ%l>TV2{{?6y4pI%la6w5betkr1>lr^h?(0nRl$@WU9JlK!zr{22Wv(4%mzJAHSEj zUOVAbs4E1^OC@g037=}dIY7l1V1RV+O7Oa)(4KXof7m+8O9mWqbv# zo<&O5`*~N!)Jj!^hhN2K_=|b&JTL+qYEs;iha{)Njp`*gcbBWdP{0e7;{D z_#SFsadWpkNVS=r!$O}VVi;)!P8mDP4!;&40-zRPSL~eWZsR-JGR5|Sos{|xLcesw z?5@^oD&_W&`?IBDXxJNB;3R#!R$6h8zrB>U_rZDgM_{e}KxPyWMJF0Mql?vu8C4ez z<9`S7`$bm%P}7!b{cGjaCTCOzG;3s~GkltYSH@9DQ76T|hvY;awa;kqZ;_XIX0mI7 z!_LO@nTKBo8Z2v9{AT^N2*vvwN0)wr?u!H0KPMBPkGxo*Zqd`X_b`_VhCTD$Iw*{N zz3yr0vFhG{;2Tyb5HRq(R!lPK#}=i;r=m#LS=Z{L5n;9vOj%(kv`wXK_OcKt{#imn zLWX=Hq7!772#41YoGsaP*-omXP_Tc7rhUrC78t;Np4%;n?k_7F&~ZV;#XL;xny#OK zk8?QVcrmM^{hh|7iO;)@P@4*IHtOVhcP^anZ&crMzl7(8T%zn?^hmnr8I4w8?6ViC z_DkivRY41}yU1UApQN5VYifA$klJ7V+@sP(u*6eb{J$o(0QEY#F%a03hV!Om-4ji` zpR~z_Z`e`bydStT9zo6zfwL`t?TN6}I5(g7Fv$m!G1{i;jvsRF(L|KC)8h>bVuSXb zcB}{2B%4v4GkX~aP%;6-s;3Ayr>&TZKgv*lF8YVC5`EFt#T@CZ{ghn_-GuU|x+L-X z`^Qhihu)Jg8t}PK!4HdO>>i$Bg6fxkDk>w14 z#>sXw)SOPvKKLp?D>C!?FKbhsx6*;Wfj(sY_JceU4*k8O?I~8Q%EeyghULR^y(;*5 zj!~?wyn8W;mf!@skDHh4yjmv|wJ+t?fbu0bv9ve)=_d7lzD>_n*oPTnB zK_2YeHV_;q(o%sgx%i1x^CVOO>!JjMu?bQnWAsCZf!a!A7smnDN?+S%*Bu3VmksUK zn*YyPf3#g(AAeL8Y+MOwO>Ub<4tqvDy5qSS30){@!N_w8#YvK}8oK~K!#ef2`??^@ z8AAs`&5#lxo)@xTcbBc%9?rtCI6)W<$9>(a#@NOJS={uwU4#T1~oA`?u zrB5vVy0X%8GcyKWQ!!8gG|2qCteD_l0{0p?zfhaFNWp+Z5hBj`=I!25gQfGj(ajnb zR+#&y`s1Uaxi=PiZx_?S9@quvNa_{s3->F}C$}cbm(iqjfoZ%$Yis7W{@~sC5^L(M z;36c3j~E}Og3UJRzDJQZ)3R~bz3%7Nxl>sg>f8DHq5w~I&-Hd8!QgRKdn+sEJg8Y< zwt_io;>|rR;Io;LxS{n1QTiQO!Y8Z7{sy6$#H?ksMk#qzMVmoH@s+Yhk47BzcB_eg zozF4otzTuQ@LpH93s&$B;QsRK>qB`LLQ*R(CeLx5=!*Sjd@jvg6(C1Q=3vz2mW220(z*w)~5%;HeR<(Qry~;2q2NE z$K>OoV|a4@A+nv+-b(E%eDlayRqt%S$!o>)V7vW>s^q~zlGZf{8#8L7U>|Ra%y%Hu z#4Lbj@5z-P>i*D{g5KLLB<%%B*NR`)McZ8RvC~4n%Um7Xoc|PRH{n=Hy^LGGrkU-q zdXqd0Cj8R(mkc52B6Q-|x&4x`|0yspgmm50UCtyBHu`NwRFZY^VbG6Wde(chsPhFu zNOFiZK}MJIYQWiGpq7RPjkS?+hCC84J?g;?(tCc8&^;1c7hq{0V)9t~5FAL*O#|R7 zJep$!RE2Zf;Ets2g$SEa?TG$~zTg?!0Mp^8Ny{@v4@$TWV|_jubT zdPq|=n2AN~W1VNljG$FtyugDQgDIA)L8&((EuwOK>O5fm2Z>AsPNmR{K|wLa>#!Tc z6PlV<<3*~KB+9FXR+FC^*J0;ZU7GNWZiDi-|CMKeVT`~r0-24pDsMER(9uH6SV&~T zDQWaf%M$~?4e=ho-659^_F5p2yup-1MEg{Il{H;MZ?^c0f)Y!6u@{NT=vb3kdWcFG z6=|$L?uOg<%tDNnik!Aq1{7 z4 zQfmyu>b`<&w$tCOh7i-XgH(9Qc_)z&=tJ-ys_n_p27%#{O-kZneJ@sB2a zhzMw1%O1e^*wrqkHbDuTSMMc9qp}AqcC>oyx)zSExRXC-Z`Y9kod(5HnG3M*5lptPMdn5(X{d z1n106u(A~_-(jwAt7@!5Q7UsEoeiPnE}kb=QFwu)?y{*nkf+{Mq|1S{a)3*2!D=!K z-}}>dZq{s5Or#7s^|94Q66lt7 zU>PR|O1vP!c@iXC7^dvLW!e{*pXlM?3LTGw z6UqATFwD%tAvxrEc%YV45ER@sG9DyS5q#zit^iPrXn2EQp^u0kFD@uYX3I}X(4#0I zc?V)0w_Dn7;;0JYdBNVTGggwh<}{#YaW79o>3G}SAK-nTEWrLLNU-+-QYvJ&6-9>e zYITD{=i6z~*@xBV$I{e+n&L|#z2cC)hzNFCJlY%?T$A4WGRkH#>p_|pV** zm*dE{J*$+2#$)XCVh^dY)qxrWnvh85rT{1bGyxwc7T}5P&!yVz`25CoUl5Ph;N8c# ze{a1*(7n9H{u-~&#jK>Jubx_jvpHTaXH6|{9STI%Twp@G{(R0&i@($FhBY*`z8nWE z2!YHu%LT_eaiV&nv+z{{A$?cu4YW9LcspB(gXvJajX&j4{`o^3fWAOaQLxG(Ze(#0 zCXn&_vxs8rjk!fMke48@3wS1?K1gH?G&3+taJIZBE_t%owVD=Z_h^$4Co!OIW`!JL zsVjn1kOrTR@`>~jQqB4wO(B5CC`w-@i?V0+H@7_oH9wuM%Zj;fmBf&e7w3mR;lfq- z-csV}5O>^&VG?sw_g<$ma$TJ0g7YnBZhSMmhAY5^i6SlyXO>Rw?dN|_iWkQf$a+x} z6DoFDr-l0&vdlg}g~Mv}H_5#LZP=bxFAqKYQRr9x+Xoi8A&6OujZ*j#S%Zl=dxyuDg<1uw^1Fthv*M*bj+yj!k1W=Z< z>c+W#2bwrd!(Xl;$FjK6_sn#J(0@tqce5J0^&B}e=!Jdx;=d4!6)}?aUjB;EGJfL; z*Z@qZY(eScFT-rg(rKc$w?Ez=WhO*6`~pTFT8a*mZn#CHg&HKim%y>t8%=5b_3*xX z&}hTHT2Iu(tBZsUUfdUc2r{T$ypbl(p?btq^5m$%rUWlgtO)f{AVn=OnY_s|O?BT8v{TSC=^{_fP>%VFcQhdZ0QCE*UWThZE zL~c73Y-iK5BR>WLJANx2=X!Z4{7v#NxEX?b?&RUXp<&k^u4eMia#h-3cI~WZbVIR; zb5Bk($)2D;4ponb6o|b#>fPcx_P-?mS1Ho>0cb&Dby}x(zIc{>)$ll+z8ztLj{yE< zFJca>xAJ#o_2K5kCI7$T5N?hZ9xi)i9>o-Cdqk)}Y&o(Z)_$P=`AVuja}^UUKB6Si z^62@Vt@?+?z0FUGt=i|;2{g~={;SOL&pLwty~lrk_{X9^*dF{R3=oJ**nhXaArJ#_ u&iJo}_xOME0E!9y-(vp=_y0eFU@iv*2MA4rCnIok_Cn$1(;_(|-~R_o^0$uw literal 0 HcmV?d00001 diff --git a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss index 55f17a795e..2e26264730 100644 --- a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss +++ b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss @@ -22,17 +22,23 @@ i.e. @use "uswds-core" as *; +iframe:focus, [href]:focus, [tabindex]:focus, [contentEditable=true]:focus { + outline: units(1px) dotted color('blue-40v'); + outline: units(1px) auto color('blue-40v'); + outline-offset: 0.3rem; +} + .usa-header--extended { .usa-logo { font-family: family("sans"); - margin: units(4) 0; + margin: units(2) 0 units(1); @include at-media-max('desktop') { margin: units(4) 0 units(4) units(2); } img { - @include at-media($theme-header-min-width) { - width: 80px; - height: 70px; + height: 35px; + @include at-media('desktop') { + height: 60px; } } } diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index 6b33fed058..210ac01e5f 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -21,7 +21,7 @@ {% endblock %} {% block meta %} - + {% endblock %} {% endblock %} diff --git a/app/templates/components/components/header/template.njk b/app/templates/components/components/header/template.njk index a4cd0d9e2c..0681fb3fb3 100644 --- a/app/templates/components/components/header/template.njk +++ b/app/templates/components/components/header/template.njk @@ -47,14 +47,13 @@