From b6353c41e5db823b0980915f6b237f1555831e71 Mon Sep 17 00:00:00 2001 From: alexjanousekGSA Date: Sun, 12 Jan 2025 17:42:15 -0500 Subject: [PATCH] Removed best practices flag --- .ds.baseline | 4 +- app/__init__.py | 8 - app/config.py | 3 - app/main/views/index.py | 12 +- app/main/views/sub_navigation_dictionaries.py | 4 - app/templates/components/header.html | 34 +- app/templates/views/guidance/index.html | 321 ++++++------------ deploy-config/demo.yml | 1 - deploy-config/production.yml | 1 - deploy-config/sandbox.yml | 1 - deploy-config/staging.yml | 1 - manifest.yml | 1 - tests/app/main/views/test_index.py | 3 +- .../test_best_practices_content_pages.py | 60 ++-- urls.js | 21 ++ 15 files changed, 162 insertions(+), 313 deletions(-) diff --git a/.ds.baseline b/.ds.baseline index 56c3afc7d..666119f50 100644 --- a/.ds.baseline +++ b/.ds.baseline @@ -161,7 +161,7 @@ "filename": "app/config.py", "hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc", "is_verified": false, - "line_number": 123, + "line_number": 120, "is_secret": false } ], @@ -684,5 +684,5 @@ } ] }, - "generated_at": "2024-11-21T23:08:45Z" + "generated_at": "2025-01-12T22:42:11Z" } diff --git a/app/__init__.py b/app/__init__.py index 6f9f15e83..54248bda0 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -168,20 +168,12 @@ def _csp(config): def create_app(application): - application.config["FEATURE_BEST_PRACTICES_ENABLED"] = ( - os.getenv("FEATURE_BEST_PRACTICES_ENABLED", "false").lower() == "true" - ) - @application.context_processor def inject_feature_flags(): - feature_best_practices_enabled = application.config.get( - "FEATURE_BEST_PRACTICES_ENABLED", False - ) feature_about_page_enabled = application.config.get( "FEATURE_ABOUT_PAGE_ENABLED", False ) return dict( - FEATURE_BEST_PRACTICES_ENABLED=feature_best_practices_enabled, FEATURE_ABOUT_PAGE_ENABLED=feature_about_page_enabled, ) diff --git a/app/config.py b/app/config.py index 146230047..a82c9a1ab 100644 --- a/app/config.py +++ b/app/config.py @@ -87,9 +87,6 @@ class Config(object): "tts-benefits-studio@gsa.gov", ], } - FEATURE_BEST_PRACTICES_ENABLED = ( - getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true" - ) FEATURE_ABOUT_PAGE_ENABLED = getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true" diff --git a/app/main/views/index.py b/app/main/views/index.py index fa18b0998..f7a8c231c 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -25,11 +25,6 @@ from app.utils.user import user_is_logged_in # Hook to check for feature flags @main.before_request def check_feature_flags(): - if request.path.startswith("/guides") and not current_app.config.get( - "FEATURE_BEST_PRACTICES_ENABLED", False - ): - abort(404) - if request.path.startswith("/about") and not current_app.config.get( "FEATURE_ABOUT_PAGE_ENABLED", False ): @@ -40,8 +35,8 @@ def check_feature_flags(): def test_feature_flags(): return jsonify( { - "FEATURE_BEST_PRACTICES_ENABLED": current_app.config[ - "FEATURE_BEST_PRACTICES_ENABLED" + "FEATURE_ABOUT_PAGE_ENABLED": current_app.config[ + "FEATURE_ABOUT_PAGE_ENABLED" ] } ) @@ -272,9 +267,6 @@ def guidance_index(): return render_template( "views/guidance/index.html", navigation_links=using_notify_nav(), - feature_best_practices_enabled=current_app.config[ - "FEATURE_BEST_PRACTICES_ENABLED" - ], ) diff --git a/app/main/views/sub_navigation_dictionaries.py b/app/main/views/sub_navigation_dictionaries.py index 885e200ef..b360aed06 100644 --- a/app/main/views/sub_navigation_dictionaries.py +++ b/app/main/views/sub_navigation_dictionaries.py @@ -33,10 +33,6 @@ def using_notify_nav(): {"name": "Delivery Status", "link": "main.message_status"}, {"name": "Guidance", "link": "main.guidance_index"}, ] - if not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED"): - nav_items = [ - item for item in nav_items if item["link"] != "main.best_practices" - ] return nav_items diff --git a/app/templates/components/header.html b/app/templates/components/header.html index 45f467c26..4c04200be 100644 --- a/app/templates/components/header.html +++ b/app/templates/components/header.html @@ -1,20 +1,13 @@ -{% set is_information_section = FEATURE_ABOUT_PAGE_ENABLED and ( - request.path.startswith('/about') or - request.path.startswith('/join-notify') or - request.path.startswith('/contact') -) %} +{% set is_about_page = request.path.startswith('/about') %} +{% set is_join_notify_page = request.path.startswith('/join-notify') %} +{% set is_contact_page = request.path.startswith('/contact') %} +{% set is_information_section = is_about_page or is_join_notify_page or is_contact_page %} {% if current_user.is_authenticated %} {% set navigation = [ {"href": url_for("main.show_accounts_or_dashboard"), "text": "Current service", "active": header_navigation.is_selected('accounts-or-dashboard')}, - {"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')} -] %} - -{% if FEATURE_BEST_PRACTICES_ENABLED %} -{% set navigation = navigation + [{"href": url_for('main.best_practices'), "text": "Guides", "active": header_navigation.is_selected('best_practices')}] %} -{% endif %} - -{% set navigation = navigation + [ + {"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')}, + {"href": url_for('main.best_practices'), "text": "Guides", "active": header_navigation.is_selected('best_practices')}, {"href": url_for('main.features'), "text": "Features", "active": header_navigation.is_selected('features')}, {"href": url_for('main.support'), "text": "Contact us", "active": header_navigation.is_selected('support')} ] %} @@ -41,16 +34,15 @@ {% endif %} {% else %} -{% set navigation = [] %} - -{% if FEATURE_ABOUT_PAGE_ENABLED %} -{% set navigation = navigation + [ - {"href": url_for('main.about_notify'), "text": "About Notify", "active": is_information_section}, - {"href": url_for('main.join_notify'), "text": "Join Notify", "active": request.path.startswith('/join-notify')}, - {"href": url_for('main.contact'), "text": "Contact us", "active": request.path.startswith('/contact')} +{% set navigation = [ + {"href": url_for('main.about_notify'), "text": "About Notify", "active": is_about_page}, + {"href": url_for('main.join_notify'), "text": "Join Notify", "active": is_join_notify_page}, + {"href": url_for('main.contact'), "text": "Contact us", "active": is_contact_page} ] %} {% endif %} -{% endif %} + + + diff --git a/app/templates/views/guidance/index.html b/app/templates/views/guidance/index.html index 2e63c6212..8a8ac0e34 100644 --- a/app/templates/views/guidance/index.html +++ b/app/templates/views/guidance/index.html @@ -8,245 +8,118 @@ {% endblock %} {% block content_column_content %} +

Guidance

-

Guidance

+

Notify allows you to easily create templates for messages for your recipients. You can customize messages to encourage +your recipient to manage their benefits and increase follow-through.

+

Below we explain how to:

-

Notify allows you easily to create templates for messages for your recipients. You can customize messages to encourage - your recipient to manage their benefits and increase follow through.

-

Below we explain how to:

+ - +{# Format content #} +

Format your content

+

Effective texts will help your message recipients take the steps needed to secure and keep the benefits and services +they depend on. To craft an effective text:

- {# Format content #} -

Format your content

- {% if not feature_best_practices_enabled %} -

Effective texts will help your message recipients take the steps needed to secure and keep the benefits and services - they depend on. To craft an effective text:

+ - - {% endif %} -

To create and format your message

-
    -
  1. All messages start from a template
  2. -
  3. Click "Send Messages". You'll see existing templates.
  4. -
  5. Add a new template or choose an existing template and select Edit.
  6. -
+

To create and format your message

+
    +
  1. All messages start from a template
  2. +
  3. Click "Send Messages". You'll see existing templates.
  4. +
  5. Add a new template or choose an existing template and select Edit.
  6. +
- {% if not feature_best_practices_enabled %} - {# Add links #} - -

When composing a text message, links to websites or online applications can help your recipient respond quickly.

+{# Add links #} + +

When composing a text message, links to websites or online applications can help your recipient respond quickly.

- + -

About link-shortening services

-

We do not recommend using a third-party link-shortening service because:

- - {% endif %} +

About link-shortening services

+

We do not recommend using a third-party link-shortening service because:

+ - {# Personalize content #} -

Personalize your content

-

Personalizing your content can increase response rates and help the recipient know the text is legitimate.

- +{# Personalize content #} +

Personalize your content

+

Personalizing your content can increase response rates and help the recipient know the text is legitimate.

+ -

To personalize your content

-
    -
  1. Add a placeholder to your content by placing two brackets around the personalized elements.
  2. -
  3. You can manually enter the personalized content or you can upload a spreadsheet with the details and let Notify do the - work for you. See data preparation.
  4. -
+

To personalize your content

+
    +
  1. Add a placeholder to your content by placing two brackets around the personalized elements.
  2. +
  3. You can manually enter the personalized content or you can upload a spreadsheet with the details and let Notify do the + work for you. See data preparation.
  4. +
-

Example

-

To personalize with the recipient's first name and include a reference number:

-

State WIC: Hello ((first name)), your reference is ((ref number)). Please provide this number when you call 555-123-1234 to make an appointment.

+

Example

+

To personalize with the recipient's first name and include a reference number:

+

State WIC: Hello ((first name)), your reference is ((ref number)). Please provide this number when you call 555-123-1234 to make an appointment.

-

Note that variations in the length of personalized content can impact the length of specific messages, and may affect - the number of parts used.

+

Note that variations in the length of personalized content can impact the length of specific messages, and may affect +the number of parts used.

- {# Add conditional content #} -

Add conditional content

-

Conditional (or optional) content appears only when a recipient meets certain criteria. This feature allows you to make - all or part of the message contingent upon specific criteria associated with the recipient.

+{# Add conditional content #} +

Add conditional content

+

Conditional (or optional) content appears only when a recipient meets certain criteria. This feature allows you to make +all or part of the message contingent upon specific criteria associated with the recipient.

-

To add conditional content

-
    -
  1. Use two brackets and ?? to define the conditional content.
  2. -
  3. You can manually enter the conditional content or you can upload a spreadsheet with the personal details and let Notify - do the work for you. See data preparation.
  4. -
+

To add conditional content

+
    +
  1. Use two brackets and ?? to define the conditional content.
  2. +
  3. You can manually enter the conditional content or you can upload a spreadsheet with the personal details and let Notify + do the work for you. See data preparation.
  4. +
-

Examples

-
    -
  1. If you only want to show something to people who are under 18: -
    -

    State SNAP: Renewal applications are due by March 15. ((under18??Please get your application signed by a parent or - guardian.))

    -
  2. -
  3. - If you want to make people who are homebound aware of the option of virtual visits (but not other message recipients): -
    -

    State Medicaid: Please call 555-123-1234 to schedule an appointment. ((homebound??Virtual visits are available.))

    -
  4. -
  5. - If you want to send a messages in different languages to different recipients: -
    -

    ((English??We’ve identified unauthorized use on your EBT account. Call the phone number on the back of your card to - cancel or go to your local CSO for immediate replacement.))((Spanish??Hemos identificado un uso no autorizado en su - cuenta EBT. Llame al número de teléfono que aparece en el reverso de su tarjeta para cancelarla o diríjase a su CSO - local para que se la sustituyan inmediatamente.))

    -
  6. -
+

Examples

+
    +
  1. If you only want to show something to people who are under 18: +
    +

    State SNAP: Renewal applications are due by March 15. ((under18??Please get your application signed by a parent or + guardian.))

    +
  2. +
  3. + If you want to make people who are homebound aware of the option of virtual visits (but not other message recipients): +
    +

    State Medicaid: Please call 555-123-1234 to schedule an appointment. ((homebound??Virtual visits are available.))

    +
  4. +
  5. + If you want to send a messages in different languages to different recipients: +
    +

    ((English??We’ve identified unauthorized use on your EBT account. Call the phone number on the back of your card to + cancel or go to your local CSO for immediate replacement.))((Spanish??Hemos identificado un uso no autorizado en su + cuenta EBT. Llame al número de teléfono que aparece en el reverso de su tarjeta para cancelarla o diríjase a su CSO + local para que se la sustituyan inmediatamente.))

    +
  6. +
+... - {# Identify your program #} -

Identify your program

-

You can help your recipients identify your texts as legitimate by customizing your messages to clearly state who they - are from. Consider using the program or benefit name that is most familiar to your recipients.

- -

To customize your program name

-

To change the text message sender from the default service name:

-
    -
  1. Go to the Settings page
  2. -
  3. Select “Start text messages with service name.”
  4. -
  5. Change the service name to a familiar program or benefit.
  6. -
- - {# Prepare your data #} -

Prepare your data

-

The easiest and most efficient way to personalize your content is by uploading a spreadsheet. Notify can accommodate - many file formats and structures.

- -

File format

-

Notify can accept files in the following formats: CSV, TSV, ODS, and Microsoft Excel.

- -

File structure

- - -

Formatting personalized content

-

If you are sending a message with personalized content, such as the first name of the recipient or the appointment time - and location, the names of the column headings have to match the indicator included in the message template.

-

For example, if the personalized content is the first name of the recipient, and we are using the spreadsheet below, the - indicator in the message needs to be ((First name)), not ((firstname)) or ((name)).

- -

Formatting conditional content

-

If you are sending messages with conditional content, such as content based on the recipient’s preferred language or - location, the flag to receive the content needs to be captured in its own column with a Yes or No (Y/N) flag.

- -

Example

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Example -
Phone numberFirst nameLast nameSpanishEnglishDateTimeLocation
123-456-7890LuluPraetherNYNovember 2, 20233:25123 Ford Rd.
234-567-8901SelaAppelYNNovember 2, 20234:00123 Ford Rd.
123-456-7890DexterMoseleyNYNovember 2, 20232:00123 Ford Rd.
-
- - {% if not feature_best_practices_enabled %} - {# Preventing fraud #} -

Preventing fraud

-

Texting fraud is ever prevalent and while we can’t eliminate the risk, we can reduce the chances that recipients will - fall victim to fraud.

-
    -
  1. Never send unnecessary or protected private information.
  2. -
  3. Remind your recipients that text messaging is not a secure means of communication and they should not send you private - information via text.
  4. -
  5. Only include links to websites and online applications that are secure.
  6. -
  7. Send an introductory text letting recipients know you will be texting them and to save the number in their phone.
  8. -
  9. Include an auto-response with the name of your organization and a contact phone number.
  10. -
- -

Examples

-
    -
  1. Introductory text: -
    -

    State Transit Dept: We're piloting a new way to get important reminders to our staff. Save this number to your phone, - you'll receive updates from us here.

    -
  2. -
  3. Auto-response text: -
    -

    State Agency: This number is unmonitored. To contact us, call us at 555-123-1234. We will never ask for personal details - in a text. If you have questions about how to protect your privacy, see statename.gov/privacy.

    -
  4. -
- {% endif %} {% endblock %} diff --git a/deploy-config/demo.yml b/deploy-config/demo.yml index 05d167f4b..2787b130e 100644 --- a/deploy-config/demo.yml +++ b/deploy-config/demo.yml @@ -7,4 +7,3 @@ cloud_dot_gov_route: notify-demo.app.cloud.gov redis_enabled: 1 nr_agent_id: '1134302465' nr_app_id: '1083160688' -FEATURE_BEST_PRACTICES_ENABLED: true diff --git a/deploy-config/production.yml b/deploy-config/production.yml index 9f5cffc89..c27f93744 100644 --- a/deploy-config/production.yml +++ b/deploy-config/production.yml @@ -7,4 +7,3 @@ cloud_dot_gov_route: notify.app.cloud.gov redis_enabled: 1 nr_agent_id: '1050708682' nr_app_id: '1050708682' -FEATURE_BEST_PRACTICES_ENABLED: false diff --git a/deploy-config/sandbox.yml b/deploy-config/sandbox.yml index 5cee4f053..58180f409 100644 --- a/deploy-config/sandbox.yml +++ b/deploy-config/sandbox.yml @@ -12,4 +12,3 @@ SECRET_KEY: sandbox-notify-secret-key nr_agent_id: '' nr_app_id: '' NR_BROWSER_KEY: '' -FEATURE_BEST_PRACTICES_ENABLED: true diff --git a/deploy-config/staging.yml b/deploy-config/staging.yml index 036f4472e..0feb07a7f 100644 --- a/deploy-config/staging.yml +++ b/deploy-config/staging.yml @@ -7,4 +7,3 @@ cloud_dot_gov_route: notify-staging.app.cloud.gov redis_enabled: 1 nr_agent_id: '1134291385' nr_app_id: '1031640326' -FEATURE_BEST_PRACTICES_ENABLED: false diff --git a/manifest.yml b/manifest.yml index 3e5f13b4c..8f8bae937 100644 --- a/manifest.yml +++ b/manifest.yml @@ -62,4 +62,3 @@ applications: LOGIN_DOT_GOV_CERTS_URL: ((LOGIN_DOT_GOV_CERTS_URL)) # feature flagging - FEATURE_BEST_PRACTICES_ENABLED: ((FEATURE_BEST_PRACTICES_ENABLED)) diff --git a/tests/app/main/views/test_index.py b/tests/app/main/views/test_index.py index 3a4c281b9..faf381725 100644 --- a/tests/app/main/views/test_index.py +++ b/tests/app/main/views/test_index.py @@ -121,8 +121,7 @@ def test_static_pages(client_request, mock_get_organization_by_domain, view, moc "guidance_index", ] return ( - not current_app.config["FEATURE_BEST_PRACTICES_ENABLED"] - and view in feature_flagged_views + view in feature_flagged_views ) request = partial(client_request.get, "main.{}".format(view)) diff --git a/tests/end_to_end/test_best_practices_content_pages.py b/tests/end_to_end/test_best_practices_content_pages.py index 5a75f9694..9f805962e 100644 --- a/tests/end_to_end/test_best_practices_content_pages.py +++ b/tests/end_to_end/test_best_practices_content_pages.py @@ -16,43 +16,39 @@ def test_best_practices_side_menu(authenticated_page): page.wait_for_load_state("domcontentloaded") check_axe_report(page) - response = page.request.get(f"{E2E_TEST_URI}/test/feature-flags") - feature_flags = response.json() - feature_best_practices_enabled = feature_flags.get("FEATURE_BEST_PRACTICES_ENABLED") + # Test Best Practices navigation + page.get_by_role("link", name="Best Practices").click() + expect(page).to_have_title(re.compile("Best Practice")) - if feature_best_practices_enabled: - page.get_by_role("link", name="Best Practices").click() - expect(page).to_have_title(re.compile("Best Practice")) + page.get_by_role("link", name="Clear goals", exact=True).click() + expect(page).to_have_title(re.compile("Establish clear goals")) - page.get_by_role("link", name="Clear goals", exact=True).click() - expect(page).to_have_title(re.compile("Establish clear goals")) + page.get_by_role("link", name="Rules and regulations").click() + expect(page).to_have_title(re.compile("Rules and regulations")) - page.get_by_role("link", name="Rules and regulations").click() - expect(page).to_have_title(re.compile("Rules and regulations")) + page.get_by_role("link", name="Establish trust").click() + expect(page).to_have_title(re.compile("Establish trust")) - page.get_by_role("link", name="Establish trust").click() - expect(page).to_have_title(re.compile("Establish trust")) + page.get_by_role("link", name="Write for action").click() + expect(page).to_have_title(re.compile("Write texts that provoke")) - page.get_by_role("link", name="Write for action").click() - expect(page).to_have_title(re.compile("Write texts that provoke")) + page.get_by_role("link", name="Multiple languages").click() + expect(page).to_have_title(re.compile("Text in multiple languages")) - page.get_by_role("link", name="Multiple languages").click() - expect(page).to_have_title(re.compile("Text in multiple languages")) + page.get_by_role("link", name="Benchmark performance").click() + expect(page).to_have_title(re.compile("Measuring performance with")) - page.get_by_role("link", name="Benchmark performance").click() - expect(page).to_have_title(re.compile("Measuring performance with")) + parent_link = page.get_by_role("link", name="Establish trust") + parent_link.hover() - parent_link = page.get_by_role("link", name="Establish trust") - parent_link.hover() + submenu_item = page.get_by_role("link", name=re.compile("Get the word out")) + submenu_item.click() - submenu_item = page.get_by_role("link", name=re.compile("Get the word out")) - submenu_item.click() + expect(page).to_have_url(re.compile(r"#get-the-word-out")) - expect(page).to_have_url(re.compile(r"#get-the-word-out")) - - anchor_target = page.locator("#get-the-word-out") - expect(anchor_target).to_be_visible() - anchor_target.click() + anchor_target = page.locator("#get-the-word-out") + expect(anchor_target).to_be_visible() + anchor_target.click() def test_breadcrumbs_best_practices(authenticated_page): @@ -63,10 +59,6 @@ def test_breadcrumbs_best_practices(authenticated_page): page.wait_for_load_state("domcontentloaded") check_axe_report(page) - response = page.request.get(f"{E2E_TEST_URI}/test/feature-flags") - feature_flags = response.json() - feature_best_practices_enabled = feature_flags.get("FEATURE_BEST_PRACTICES_ENABLED") - - if feature_best_practices_enabled: - page.get_by_role("link", name="Clear goals", exact=True).click() - page.locator("ol").get_by_role("link", name="Best Practices").click() + # Test Best Practices breadcrumbs + page.get_by_role("link", name="Clear goals", exact=True).click() + page.locator("ol").get_by_role("link", name="Best Practices").click() diff --git a/urls.js b/urls.js index bd693cc90..c6db0795e 100644 --- a/urls.js +++ b/urls.js @@ -32,6 +32,27 @@ const sublinks = [ label: 'Benchmark Performance', path: '/guides/benchmark-performance', }, + { + label: 'About', + path: '/about', + }, + { + label: 'Why Text Messaging', + path: '/about/why-text-messaging', + }, + { + label: 'Security', + path: '/about/security', + }, + { + label: 'Join Notify', + path: '/join-notify', + }, + { + label: 'Contact', + path: '/contact', + }, + // Add more links here as needed ];