mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-18 13:39:41 -04:00
Merge branch 'main' into 2105-contact
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import os
|
||||
import pathlib
|
||||
import secrets
|
||||
from functools import partial
|
||||
from time import monotonic
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
from urllib.parse import unquote, urlparse, urlunparse
|
||||
|
||||
import jinja2
|
||||
from flask import (
|
||||
@@ -114,6 +115,7 @@ from notifications_utils.formatters import (
|
||||
get_lines_with_normalised_whitespace,
|
||||
)
|
||||
from notifications_utils.recipients import format_phone_number_human_readable
|
||||
from notifications_utils.url_safe_token import generate_token
|
||||
|
||||
login_manager = LoginManager()
|
||||
csrf = CSRFProtect()
|
||||
@@ -168,10 +170,38 @@ def create_app(application):
|
||||
|
||||
@application.context_processor
|
||||
def inject_feature_flags():
|
||||
feature_best_practices_enabled = application.config[
|
||||
"FEATURE_BEST_PRACTICES_ENABLED"
|
||||
]
|
||||
return dict(FEATURE_BEST_PRACTICES_ENABLED=feature_best_practices_enabled)
|
||||
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,
|
||||
)
|
||||
|
||||
@application.context_processor
|
||||
def inject_initial_signin_url():
|
||||
ttl = 24 * 60 * 60
|
||||
|
||||
# make and store the state
|
||||
state = generate_token(
|
||||
str(request.remote_addr),
|
||||
current_app.config["SECRET_KEY"],
|
||||
current_app.config["DANGEROUS_SALT"],
|
||||
)
|
||||
|
||||
state_key = f"login-state-{unquote(state)}"
|
||||
redis_client.set(state_key, state, ex=ttl)
|
||||
|
||||
# make and store the nonce
|
||||
nonce = secrets.token_urlsafe()
|
||||
nonce_key = f"login-nonce-{unquote(nonce)}"
|
||||
redis_client.set(nonce_key, nonce, ex=ttl)
|
||||
|
||||
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
|
||||
if url is not None:
|
||||
url = url.replace("NONCE", nonce)
|
||||
url = url.replace("STATE", state)
|
||||
|
||||
return {'initial_signin_url': url}
|
||||
|
||||
notify_environment = os.environ["NOTIFY_ENVIRONMENT"]
|
||||
|
||||
|
||||
1
app/assets/images/alarm.svg
Normal file
1
app/assets/images/alarm.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.2 KiB |
1
app/assets/images/alert.svg
Normal file
1
app/assets/images/alert.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Capa_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><g><g><g><path d="m377.64 347.666c-4.473 0-8.1 3.626-8.1 8.099s3.626 8.1 8.1 8.1c4.473 0 8.099-3.626 8.099-8.1s-3.626-8.099-8.099-8.099z"/><path d="m377.716 334.615c4.149 0 7.511-3.363 7.511-7.511v-67.172c0-4.148-3.362-7.511-7.511-7.511-4.148 0-7.511 3.363-7.511 7.511v67.172c0 4.148 3.362 7.511 7.511 7.511z"/><path d="m377.64 219.085c-7.974 0-15.716 1.011-23.105 2.912v-14.937c0-59.921-37.644-111.208-90.522-131.476 2.741-6.491 4.267-13.614 4.267-21.092 0-30.047-24.445-54.492-54.492-54.492s-54.491 24.445-54.491 54.491c0 7.469 1.522 14.586 4.256 21.071-16.063 6.135-30.994 15.219-44.006 26.957-3.081 2.778-3.325 7.528-.547 10.608 2.781 3.081 7.53 3.324 10.608.546 23.118-20.854 53.014-32.339 84.18-32.339 69.324 0 125.725 56.4 125.725 125.725v20.222c-32.217 14.573-54.688 47.021-54.688 84.618 0 11.997 2.288 23.47 6.45 34.005h-203.212v-138.845c0-24.475 7.036-48.196 20.346-68.599 2.267-3.474 1.288-8.128-2.187-10.394-3.474-2.266-8.129-1.288-10.394 2.186-14.907 22.851-22.787 49.41-22.787 76.807v143.829l-28.543 37.616c-1.903 2.506-2.952 5.62-2.952 8.768v27.183c0 7.996 6.505 14.501 14.501 14.501h94.92c-.468 3.102-.719 6.274-.719 9.504 0 35.036 28.504 63.541 63.541 63.541 35.036 0 63.541-28.504 63.541-63.541 0-3.232-.263-6.402-.735-9.504h29.487c4.149 0 7.511-3.363 7.511-7.511s-3.362-7.511-7.511-7.511h-249.514v-26.486l27.713-36.521h214.585c15.307 24.506 41.72 41.39 72.142 43.548v19.459h-29.946c-4.148 0-7.511 3.363-7.511 7.511s3.362 7.511 7.511 7.511h30.467c7.996 0 14.5-6.505 14.5-14.501v-20.125c47.261-4.255 84.425-44.082 84.425-92.431 0-51.178-41.636-92.814-92.814-92.814zm-127.992-148.137c-11.454-3.02-23.471-4.636-35.86-4.636-12.217 0-24.259 1.583-35.863 4.634-2.311-5.012-3.607-10.584-3.607-16.455 0-21.764 17.706-39.469 39.469-39.469s39.469 17.706 39.469 39.469c.002 5.873-1.295 11.445-3.608 16.457zm-83.427 368.007h95.144c.616 3.074.942 6.251.942 9.504 0 26.753-21.765 48.519-48.519 48.519s-48.519-21.766-48.519-48.519c.001-3.254.335-6.429.952-9.504zm211.419-49.263c-42.895 0-77.793-34.898-77.793-77.793s34.897-77.793 77.793-77.793 77.793 34.898 77.793 77.793c-.001 42.895-34.898 77.793-77.793 77.793z"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
app/assets/images/calendar.svg
Normal file
1
app/assets/images/calendar.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.0 KiB |
@@ -676,28 +676,28 @@ details form {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.best-practices-list {
|
||||
ol.guides-list {
|
||||
counter-reset: item;
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
ol.best-practices-list.set-two {
|
||||
ol.guides-list.set-two {
|
||||
counter-reset: item 6;
|
||||
}
|
||||
|
||||
ol.best-practices-list.set-three {
|
||||
ol.guides-list.set-three {
|
||||
counter-reset: item 10;
|
||||
}
|
||||
|
||||
ol.best-practices-list li {
|
||||
ol.guides-list li {
|
||||
counter-increment: item;
|
||||
margin-bottom: 15px;
|
||||
position: relative;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
ol.best-practices-list li::before {
|
||||
ol.guides-list li::before {
|
||||
content: counter(item);
|
||||
background-color: #005ea2;
|
||||
color: white;
|
||||
@@ -713,11 +713,11 @@ ol.best-practices-list li::before {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
li.best-practices {
|
||||
li.guides {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
div.best-practices {
|
||||
div.guides {
|
||||
height: 400px
|
||||
}
|
||||
|
||||
@@ -820,7 +820,7 @@ $do-dont-top-bar-width: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 758px) {
|
||||
.best-practices-flex-container {
|
||||
.guides-flex-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
@@ -898,7 +898,7 @@ li.linked-card:hover svg,
|
||||
display: block;
|
||||
}
|
||||
|
||||
.about-icon-list {
|
||||
.icon-list {
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
@@ -908,10 +908,6 @@ li.linked-card:hover svg,
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.usa-icon-list__content{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.indented-paragraph {
|
||||
margin-left: calc(24px + 4px);
|
||||
margin-top: 4px;
|
||||
|
||||
@@ -91,9 +91,7 @@ class Config(object):
|
||||
getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true"
|
||||
)
|
||||
|
||||
FEATURE_ABOUT_PAGE_ENABLED = (
|
||||
getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
|
||||
)
|
||||
FEATURE_ABOUT_PAGE_ENABLED = getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
|
||||
|
||||
|
||||
def _s3_credentials_from_env(bucket_prefix):
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import os
|
||||
import secrets
|
||||
from urllib.parse import unquote
|
||||
|
||||
from flask import abort, current_app, redirect, render_template, request, url_for
|
||||
from flask import (
|
||||
abort,
|
||||
current_app,
|
||||
jsonify,
|
||||
redirect,
|
||||
render_template,
|
||||
request,
|
||||
url_for,
|
||||
)
|
||||
from flask_login import current_user
|
||||
|
||||
from app import redis_client, status_api_client
|
||||
from app import status_api_client
|
||||
from app.formatters import apply_html_class, convert_markdown_template
|
||||
from app.main import main
|
||||
from app.main.views.pricing import CURRENT_SMS_RATE
|
||||
@@ -16,55 +20,42 @@ from app.main.views.sub_navigation_dictionaries import (
|
||||
using_notify_nav,
|
||||
)
|
||||
from app.utils.user import user_is_logged_in
|
||||
from notifications_utils.url_safe_token import generate_token
|
||||
|
||||
|
||||
# Hook to check for feature flags
|
||||
@main.before_request
|
||||
def check_feature_flags():
|
||||
if (
|
||||
request.path.startswith("/guides/best-practices")
|
||||
and not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED", False)
|
||||
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)
|
||||
if request.path.startswith("/about") and not current_app.config.get(
|
||||
"FEATURE_ABOUT_PAGE_ENABLED", False
|
||||
):
|
||||
abort(404)
|
||||
|
||||
|
||||
@main.route("/test/feature-flags")
|
||||
def test_feature_flags():
|
||||
return jsonify(
|
||||
{
|
||||
"FEATURE_BEST_PRACTICES_ENABLED": current_app.config[
|
||||
"FEATURE_BEST_PRACTICES_ENABLED"
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@main.route("/")
|
||||
def index():
|
||||
if current_user and current_user.is_authenticated:
|
||||
return redirect(url_for("main.choose_account"))
|
||||
|
||||
ttl = 24 * 60 * 60
|
||||
|
||||
# make and store the state
|
||||
state = generate_token(
|
||||
str(request.remote_addr),
|
||||
current_app.config["SECRET_KEY"],
|
||||
current_app.config["DANGEROUS_SALT"],
|
||||
)
|
||||
state_key = f"login-state-{unquote(state)}"
|
||||
redis_client.set(state_key, state, ex=ttl)
|
||||
|
||||
# make and store the nonce
|
||||
nonce = secrets.token_urlsafe()
|
||||
nonce_key = f"login-nonce-{unquote(nonce)}"
|
||||
redis_client.set(nonce_key, nonce, ex=ttl)
|
||||
|
||||
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
|
||||
if url is not None:
|
||||
url = url.replace("NONCE", nonce)
|
||||
url = url.replace("STATE", state)
|
||||
return render_template(
|
||||
"views/signedout.html",
|
||||
sms_rate=CURRENT_SMS_RATE,
|
||||
counts=status_api_client.get_count_of_live_services_and_organizations(),
|
||||
initial_signin_url=url,
|
||||
counts=status_api_client.get_count_of_live_services_and_organizations()
|
||||
)
|
||||
|
||||
|
||||
@@ -216,61 +207,61 @@ def trial_mode_new():
|
||||
@user_is_logged_in
|
||||
def best_practices():
|
||||
return render_template(
|
||||
"views/best-practices/best-practices.html",
|
||||
"views/guides/best-practices.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/guides/best-practices/clear-goals")
|
||||
@main.route("/guides/clear-goals")
|
||||
@user_is_logged_in
|
||||
def clear_goals():
|
||||
return render_template(
|
||||
"views/best-practices/clear-goals.html",
|
||||
"views/guides/clear-goals.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/guides/best-practices/rules-and-regulations")
|
||||
@main.route("/guides/rules-and-regulations")
|
||||
@user_is_logged_in
|
||||
def rules_and_regulations():
|
||||
return render_template(
|
||||
"views/best-practices/rules-and-regulations.html",
|
||||
"views/guides/rules-and-regulations.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/guides/best-practices/establish-trust")
|
||||
@main.route("/guides/establish-trust")
|
||||
@user_is_logged_in
|
||||
def establish_trust():
|
||||
return render_template(
|
||||
"views/best-practices/establish-trust.html",
|
||||
"views/guides/establish-trust.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/guides/best-practices/write-for-action")
|
||||
@main.route("/guides/write-for-action")
|
||||
@user_is_logged_in
|
||||
def write_for_action():
|
||||
return render_template(
|
||||
"views/best-practices/write-for-action.html",
|
||||
"views/guides/write-for-action.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/guides/best-practices/multiple-languages")
|
||||
@main.route("/guides/multiple-languages")
|
||||
@user_is_logged_in
|
||||
def multiple_languages():
|
||||
return render_template(
|
||||
"views/best-practices/multiple-languages.html",
|
||||
"views/guides/multiple-languages.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/guides/best-practices/benchmark-performance")
|
||||
@main.route("/guides/benchmark-performance")
|
||||
@user_is_logged_in
|
||||
def benchmark_performance():
|
||||
return render_template(
|
||||
"views/best-practices/benchmark-performance.html",
|
||||
"views/guides/benchmark-performance.html",
|
||||
navigation_links=best_practices_nav(),
|
||||
)
|
||||
|
||||
@@ -287,6 +278,13 @@ def guidance_index():
|
||||
)
|
||||
|
||||
|
||||
@main.route("/contact")
|
||||
def contact():
|
||||
return render_template(
|
||||
"views/about/contact.html",
|
||||
)
|
||||
|
||||
|
||||
@main.route("/about")
|
||||
def about_notify():
|
||||
return render_template(
|
||||
@@ -295,10 +293,18 @@ def about_notify():
|
||||
)
|
||||
|
||||
|
||||
@main.route("/about/contact")
|
||||
def contact():
|
||||
@main.route("/about/security")
|
||||
def about_security():
|
||||
return render_template(
|
||||
"views/about/contact.html",
|
||||
"views/about/security.html",
|
||||
navigation_links=about_notify_nav(),
|
||||
)
|
||||
|
||||
|
||||
@main.route("/about/why-text-messaging")
|
||||
def why_text_messaging():
|
||||
return render_template(
|
||||
"views/about/why-text-messaging.html",
|
||||
navigation_links=about_notify_nav(),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
from flask import current_app
|
||||
|
||||
|
||||
def features_nav():
|
||||
return [
|
||||
{
|
||||
@@ -22,46 +25,20 @@ def features_nav():
|
||||
|
||||
|
||||
def using_notify_nav():
|
||||
return [
|
||||
{
|
||||
"name": "Get started",
|
||||
"link": "main.get_started",
|
||||
},
|
||||
{
|
||||
"name": "Guides",
|
||||
"link": "main.best_practices",
|
||||
},
|
||||
{
|
||||
"name": "Trial mode",
|
||||
"link": "main.trial_mode_new",
|
||||
},
|
||||
{
|
||||
"name": "Tracking usage",
|
||||
"link": "main.pricing",
|
||||
},
|
||||
{
|
||||
"name": "Delivery status",
|
||||
"link": "main.message_status",
|
||||
},
|
||||
{
|
||||
"name": "Guidance",
|
||||
"link": "main.guidance_index",
|
||||
# "sub_navigation_items": [
|
||||
# {
|
||||
# "name": "Formatting",
|
||||
# "link": "main.edit_and_format_messages",
|
||||
# },
|
||||
# {
|
||||
# "name": "Send files by email",
|
||||
# "link": "main.send_files_by_email",
|
||||
# },
|
||||
# ]
|
||||
# {
|
||||
# "name": "API documentation",
|
||||
# "link": "main.documentation",
|
||||
# },
|
||||
},
|
||||
nav_items = [
|
||||
{"name": "Get started", "link": "main.get_started"},
|
||||
{"name": "Guides", "link": "main.best_practices"},
|
||||
{"name": "Trial mode", "link": "main.trial_mode_new"},
|
||||
{"name": "Tracking usage", "link": "main.pricing"},
|
||||
{"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
|
||||
|
||||
|
||||
def best_practices_nav():
|
||||
@@ -110,8 +87,32 @@ def best_practices_nav():
|
||||
def about_notify_nav():
|
||||
return [
|
||||
{
|
||||
"name": "About notify",
|
||||
"name": "About Notify",
|
||||
"link": "main.about_notify",
|
||||
"sub_navigation_items": [
|
||||
{
|
||||
"name": "Why text messaging",
|
||||
"link": "main.why_text_messaging",
|
||||
"sub_sub_navigation_items": [
|
||||
{
|
||||
"name": "Reach people using a common method",
|
||||
"link": "main.why_text_messaging#reach-people-using-a-common-method",
|
||||
},
|
||||
{
|
||||
"name": "Improve customer experience",
|
||||
"link": "main.why_text_messaging#improve-customer-experience",
|
||||
},
|
||||
{
|
||||
"name": "What texting is best for",
|
||||
"link": "main.why_text_messaging#what-texting-is-best-for",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Security",
|
||||
"link": "main.about_security",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Contact",
|
||||
|
||||
@@ -53,7 +53,7 @@ class HeaderNavigation(Navigation):
|
||||
"establish_trust",
|
||||
"write_for_action",
|
||||
"multiple_languages",
|
||||
"benchmark_performance"
|
||||
"benchmark_performance",
|
||||
},
|
||||
"using_notify": {
|
||||
"get_started",
|
||||
|
||||
@@ -66,7 +66,20 @@
|
||||
<ul class="usa-sidenav__sublist" role="menu">
|
||||
{% for sub_item in item.sub_navigation_items %}
|
||||
<li role="menuitem">
|
||||
<a href="{{ url_for(sub_item.link.split('#')[0]) }}#{{ sub_item.link.split('#')[1] }}">{{ sub_item.name }}</a>
|
||||
<a href="{{ url_for(sub_item.link.split('#')[0]) }}#{{ sub_item.link.split('#')[1] }}">
|
||||
{{ sub_item.name }}
|
||||
</a>
|
||||
{% if sub_item.sub_sub_navigation_items %}
|
||||
<ul class="usa-sidenav__sublist usa-sidenav__sub-sublist" role="menu">
|
||||
{% for sub_sub_item in sub_item.sub_sub_navigation_items %}
|
||||
<li role="menuitem">
|
||||
<a href="{{ url_for(sub_sub_item.link.split('#')[0]) }}#{{ sub_sub_item.link.split('#')[1] }}">
|
||||
{{ sub_sub_item.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<span class="folder-heading-folder">{{ folder.name }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{{ url_for('.choose_template', service_id=service_id, template_type=template_type) }}" title="Templates" class="usa-link {% if loop.length > 2 %}folder-heading-folder-root-truncated{% endif %}">Templates</a>
|
||||
<a href="{{ url_for('.choose_template', service_id=service_id, template_type=template_type) }}" class="usa-link {% if loop.length > 2 %}folder-heading-folder-root-truncated{% endif %}">Templates</a>
|
||||
{% endif %}
|
||||
{% if not loop.last %}{{ folder_path_separator() }}{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -43,18 +43,29 @@ secondary_navigation.is_selected('settings')},
|
||||
<header class="usa-header usa-header--extended">
|
||||
<div class="usa-nav-container">
|
||||
<div class="usa-navbar">
|
||||
<div class="usa-logo display-flex flex-align-center flex-justify" id="-logo">
|
||||
<div class="logo-img display-flex">
|
||||
<a href="/">
|
||||
<span class="usa-sr-only">Notify.gov logo</span>
|
||||
<img src="{{ (asset_path | default('/static')) + 'images/notify-logo.svg' }}" alt="Notify.gov logo"
|
||||
class="usa-flag-logo margin-right-1">
|
||||
<div class="display-flex flex-align-center flex-justify">
|
||||
<div class="usa-logo display-flex flex-align-center flex-justify" id="-logo">
|
||||
<div class="logo-img display-flex">
|
||||
<a href="/">
|
||||
<span class="usa-sr-only">Notify.gov logo</span>
|
||||
<img src="{{ (asset_path | default('/static')) + 'images/notify-logo.svg' }}" alt="Notify.gov logo"
|
||||
class="usa-flag-logo margin-right-1">
|
||||
</a>
|
||||
</div>
|
||||
{% if navigation %}
|
||||
<button type="button" class="usa-menu-btn">Menu</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not current_user.is_authenticated and FEATURE_ABOUT_PAGE_ENABLED and request.path == '/about'%}
|
||||
<div class="usa-nav__login">
|
||||
<a class="usa-button usa-button login-button login-button--primary margin-right-2"
|
||||
href="{{ initial_signin_url }}">Sign
|
||||
in with <img src="{{ asset_url('images/logo-login.svg') }}" alt="Login.gov logo">
|
||||
</a>
|
||||
</div>
|
||||
{% if navigation %}
|
||||
<button type="button" class="usa-menu-btn">Menu</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<nav aria-label="Primary navigation" class="usa-nav">
|
||||
<div class="usa-nav__inner">
|
||||
@@ -89,6 +100,7 @@ secondary_navigation.is_selected('settings')},
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
{% macro breadcrumb(title, parent_menu_title, url) %}
|
||||
<nav class="navigation-service usa-breadcrumb padding-top-0">
|
||||
<ol class="usa-breadcrumb__list">
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<span class="usa-breadcrumb__label"><a href="{{ url_for('.best_practices') }}"
|
||||
class="usa-link navigation-organization-link">Best Practices</a></span>
|
||||
<span class="usa-breadcrumb__label">
|
||||
<a href="{{ url_for(url) }}" class="usa-link navigation-organization-link">
|
||||
{{ parent_menu_title }}
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
{% if title %}
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
@@ -11,3 +15,4 @@
|
||||
{% endif %}
|
||||
</ol>
|
||||
</nav>
|
||||
{% endmacro %}
|
||||
@@ -2,7 +2,7 @@
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/form.html" import form_wrapper %}
|
||||
|
||||
<div class="ajax-block-container" aria-labelledby='pill-selected-item' role="region">
|
||||
<div class="ajax-block-container" role="region">
|
||||
{% if job.scheduled %}
|
||||
|
||||
<p class="usa-body">
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% set page_title = "About notify" %}
|
||||
{% set page_title = "About Notify" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{page_title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
<!-- {% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} -->
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p>Notify.gov is a text messaging service built by and for the government. We help agencies communicate more
|
||||
@@ -17,8 +16,9 @@
|
||||
<li>Meet people where they are</li>
|
||||
<li>More effectively deliver program outcomes</li>
|
||||
<li>Save administrative costs</li>
|
||||
<li>Implement <a href="https://digital.gov/resources/delivering-digital-first-public-experience/"
|
||||
target="_blank">21st Century IDEA</a> and other directives</li>
|
||||
<li>Implement <a class="use-link usa-link--external"
|
||||
href="https://digital.gov/resources/delivering-digital-first-public-experience/" target="_blank">21st Century
|
||||
IDEA</a> and other directives</li>
|
||||
</ul>
|
||||
<p>Notify.gov is an easy-to-use, web-based platform. It requires no technical expertise or system integration — users
|
||||
can create an account and get started within minutes. We take the security and privacy of messaging data seriously
|
||||
@@ -56,9 +56,9 @@
|
||||
<ul class="usa-icon-list">
|
||||
{% for item in product_highlights %}
|
||||
<li class="usa-icon-list__item">
|
||||
<div class="usa-icon-list__content">
|
||||
<div class="usa-icon-list__content padding-left-0">
|
||||
<div class="usa-icon-list__icon display-flex flex-align-start">
|
||||
<svg aria-hidden="true" focusable="false" role="img" class="about-icon-list">
|
||||
<svg aria-hidden="true" focusable="false" role="img" class="icon-list">
|
||||
<use xlink:href="{{ asset_url('img/sprite.svg') }}{{ item.svg_src }}"></use>
|
||||
</svg>
|
||||
<b>{{item.card_heading}}</b>
|
||||
@@ -68,10 +68,8 @@
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p><a href="/join-notify">See if Notify is right for you</a></p>
|
||||
<p>Notify.gov is a product of the <a href="#" target="_blank">Public Benefits Studio</a>, a product accelerator inside
|
||||
<p><a href="#">See if Notify is right for you</a></p>
|
||||
<p>Notify.gov is a product of the <a href="#">Public Benefits Studio</a>, a product accelerator inside
|
||||
the federal government. </p>
|
||||
|
||||
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
68
app/templates/views/about/security.html
Normal file
68
app/templates/views/about/security.html
Normal file
@@ -0,0 +1,68 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% set page_title = "Security" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{page_title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "About", "main.about_notify") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base">Notify.gov is built for the needs of government agencies with fundamental system
|
||||
security processes in place to:
|
||||
</p>
|
||||
<ul>
|
||||
<li>protect user data</li>
|
||||
<li>keep systems secure</li>
|
||||
<li>manage risks around information</li>
|
||||
</ul>
|
||||
<p>
|
||||
Notify.gov operates under a full three-year <a class="use-link usa-link--external"
|
||||
href="https://digital.gov/resources/an-introduction-to-ato/" target="_blank">Authority-to-Operate (ATO)</a>. This
|
||||
federal security authorization process leverages security
|
||||
controls provided by National Institute of Standards and Technology (NIST).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Our infrastructure runs on <a class="use-link usa-link--external" href="https://www.cloud.gov/"
|
||||
target="_blank">cloud.gov</a> and utilizes several
|
||||
services through Amazon Web
|
||||
Services (AWS), including <a class="use-link usa-link--external" href="https://aws.amazon.com/sns/" target="_blank">
|
||||
AWS SNS </a> for sending SMS
|
||||
messages.
|
||||
</p>
|
||||
<p>For more information about the Notify.gov infrastructure, contact us at <a
|
||||
href="mailto:notify-support@gsa.gov">notify-support@gsa.gov</a>.</p>
|
||||
<h2>Data</h2>
|
||||
<p>
|
||||
On Notify.gov, data is encrypted both in transit and at rest. To send a message, agencies upload a spreadsheet of
|
||||
phone numbers and other necessary data from their existing data management system.
|
||||
</p>
|
||||
<p>
|
||||
Notify.gov is not a system of record, so it does not have a System of Records Notice (SORN). Agencies are
|
||||
responsible for managing their data outside of Notify.gov.
|
||||
</p>
|
||||
<h3>Data retention</h3>
|
||||
<p>
|
||||
Any data uploads that have recipient data are held for seven calendar days; personally identifiable information
|
||||
(PII) is never stored in Notify’s database.
|
||||
</p>
|
||||
<h2>Multi-Factor Authentication</h2>
|
||||
<p>
|
||||
Notify.gov uses <a class="use-link usa-link--external" href="https://login.gov/what-is-login/"
|
||||
target="_blank">Login.gov</a> for enhanced security.
|
||||
Login.gov is an extra layer of security created by the government that uses multi-factor authentication and stronger
|
||||
passwords to protect your account.
|
||||
</p>
|
||||
<p>
|
||||
To access Notify.gov, users will use a Login.gov account associated with their agency (.gov) email with one of the
|
||||
<a class="use-link usa-link--external" href="https://login.gov/help/get-started/authentication-methods/"
|
||||
target="_blank">multi-factor authentication
|
||||
methods</a> offered through Login.gov.
|
||||
</p>
|
||||
</section>
|
||||
{% endblock %}
|
||||
87
app/templates/views/about/why-text-messaging.html
Normal file
87
app/templates/views/about/why-text-messaging.html
Normal file
@@ -0,0 +1,87 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% set page_title = "Why text messaging" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
{{page_title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "About", "main.about_notify") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<h2 id="reach-people-using-a-common-method">Reach people using a common method</h2>
|
||||
<p>
|
||||
Confusing or <a class="use-link usa-link--external"
|
||||
href="https://kffhealthnews.org/news/tougher-returned-mail-policies-add-to-medicaid-enrollment-drop/"
|
||||
target="_blank">unreceived notifications</a> are one of the largest barriers to people getting and keeping
|
||||
benefits. The typical ways the government communicates with people often fall short. Low income households are more
|
||||
likely to experience housing instability, which means paper mail, already slow, can easily be missed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a class="use-link usa-link--external"
|
||||
href="https://www.pewresearch.org/internet/fact-sheet/mobile/?tabItem=64e32376-5a21-4b1d-8f8b-5f92406db984"
|
||||
target="_blank">Pew Research shows that nearly all adults in the US have a cell phone.</a> Reliance on smartphones
|
||||
for online access is especially common among Americans with lower household incomes and those with lower levels of
|
||||
formal education. Of those earning less than $30,000 a year, 28% say their mobile phone is the sole method to
|
||||
digitally connect.
|
||||
</p>
|
||||
<p>
|
||||
This means that for many people who rely on government services, cell phones may be the most reliable place to meet
|
||||
people where they already are.
|
||||
</p>
|
||||
<h2 id="improve-customer-experience">Improve customer experience</h2>
|
||||
<p>
|
||||
Text messages can deliver concise information and drive an audience to take action quickly. Timely reminders sent
|
||||
via text message have been proven to decrease re-enrollment churn and save money for administering agencies.
|
||||
</p>
|
||||
<p>
|
||||
Texting not only helps programs reach people using a nearly-universal communication method, it is a cost effective
|
||||
way to do so. With Notify.gov <a href="#">you can get started for free</a>, allowing you to try out
|
||||
texting to complement your existing communications and outreach strategies.
|
||||
</p>
|
||||
<h2 id="what-texting-is-best-for">What texting is best for</h2>
|
||||
<p>
|
||||
Agencies, like you, are already using Notify.gov to text about the following programs.
|
||||
</p>
|
||||
{% set card_contents = [
|
||||
{
|
||||
"image_src": asset_url('images/calendar.svg'),
|
||||
"card_heading": "Reminders",
|
||||
"p_text": "In a text bubble // Your Quality Control food phone interview is on ((date)) at ((time)). Failure to
|
||||
attend may lead to closure of your benefits. Call 1-800-222-3333 with questions.",
|
||||
"alt_text": "reminder text example"
|
||||
},
|
||||
{
|
||||
"image_src": asset_url('images/alert.svg'),
|
||||
"card_heading": "Alerts to take action",
|
||||
"p_text": "In a text bubble // Your household's Medicaid coverage is expiring. To keep getting Medicaid, you must
|
||||
complete your renewal by ((date)). You can renew online at dhs.state.gov…",
|
||||
"alt_text": "alerts text example"
|
||||
},
|
||||
{
|
||||
"image_src": asset_url('images/alarm.svg'),
|
||||
"card_heading": "Important status updates",
|
||||
"p_text": "In a text bubble // Your passport has been issued at the Los Angeles Passport Agency. Please come to the
|
||||
desk between 1:30pm and 2:30pm today to pick up your passport…",
|
||||
"alt_text": "status update text example"
|
||||
},
|
||||
] %}
|
||||
{% for item in card_contents %}
|
||||
<div class="radius-lg border-2px maxw-tablet">
|
||||
<div class="grid-row grid-gap-4 padding-4 padding-y-3 flex-align-center">
|
||||
<div class="grid-col flex-3">
|
||||
<p><b>{{item.card_heading}}</b></p>
|
||||
<p>{{item.p_text}}</p>
|
||||
</div>
|
||||
{% if item.image_src %}
|
||||
<img src="{{item.image_src}}" alt="{{ item.alt_text }}" class="height-15" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% set page_title = "Measuring performance with benchmarking" %}
|
||||
|
||||
@@ -7,7 +8,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base">Learn how effective your texting program can be.</p>
|
||||
@@ -19,7 +21,7 @@
|
||||
</p>
|
||||
<h2>What other texting studies have found</h2>
|
||||
<p>
|
||||
When the <a
|
||||
When the <a class="use-link usa-link--external"
|
||||
href="https://www.cbpp.org/research/food-assistance/targeted-text-message-outreach-can-increase-wic-enrollment-pilots-show"
|
||||
target="_blank">Center on Budget and Policy Priorities</a> studied WIC, they found key learnings about the
|
||||
quantity of messages delivered, how people engage with messages, and how they take action.
|
||||
@@ -78,7 +80,8 @@
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The <a href="https://codeforamerica.org/resources/texting-playbook/" target="_blank">Code for America’s Texting
|
||||
The <a class="use-link usa-link--external" href="https://codeforamerica.org/resources/texting-playbook/"
|
||||
target="_blank">Code for America’s Texting
|
||||
Playbook</a>
|
||||
reported specific learnings around appointment reminders, completing
|
||||
document submission, and maintenance reminders.
|
||||
@@ -1,11 +1,12 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% set page_title = "Best Practices" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
Best Practices
|
||||
{{page_title}}
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>Best Practices</h1>
|
||||
<p class="font-sans-lg text-base">For texting the public</p>
|
||||
@@ -23,41 +24,41 @@ Best Practices
|
||||
"svg_src": "goal",
|
||||
"card_heading": "Establish clear goals",
|
||||
"p_text": "Start with a singular purpose. Make explicit what you want to achieve.",
|
||||
"link": "/guides/best-practices/clear-goals"
|
||||
"link": "/guides/clear-goals"
|
||||
},
|
||||
{
|
||||
"svg_src": "compliant",
|
||||
"card_heading": "Follow rules & regulations",
|
||||
"p_text": "Understand what is required when texting the public.",
|
||||
"link": "/guides/best-practices/rules-and-regulations"
|
||||
"link": "/guides/rules-and-regulations"
|
||||
},
|
||||
{
|
||||
"svg_src": "trust",
|
||||
"card_heading": "Establish trust",
|
||||
"p_text": "Help your audience anticipate and welcome your texts.",
|
||||
"link": "/guides/best-practices/establish-trust"
|
||||
"link": "/guides/establish-trust"
|
||||
},
|
||||
{
|
||||
"svg_src": "runner",
|
||||
"card_heading": "Write texts that provoke action",
|
||||
"p_text": "Help your audience know what to do with the information you send.",
|
||||
"link": "/guides/best-practices/write-for-action"
|
||||
"link": "/guides/write-for-action"
|
||||
},
|
||||
{
|
||||
"svg_src": "language",
|
||||
"card_heading": "Send texts in multiple languages",
|
||||
"p_text": "What to know as you plan translated texts.",
|
||||
"link": "/guides/best-practices/multiple-languages"
|
||||
"link": "/guides/multiple-languages"
|
||||
},
|
||||
{
|
||||
"svg_src": "chart",
|
||||
"card_heading": "Measure performance with benchmarking",
|
||||
"p_text": "Learn how effective your texting program can be.",
|
||||
"link": "/guides/best-practices/benchmark-performance"
|
||||
"link": "/guides/benchmark-performance"
|
||||
}
|
||||
] %}
|
||||
|
||||
{% with card_contents=card_contents %}{% include "components/best-practices/cards.html" %}{%
|
||||
{% with card_contents=card_contents %}{% include "components/guides/cards.html" %}{%
|
||||
endwith %}
|
||||
|
||||
</section>
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% set page_title = "Establish clear goals" %}
|
||||
|
||||
@@ -7,7 +8,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base">Start with a singular purpose. Make explicit what you want to achieve.</p>
|
||||
@@ -160,7 +162,7 @@
|
||||
</div>
|
||||
<p>
|
||||
Review your drafted hypothesis with your team to make sure everyone is aligned on your desired goals. A clear and
|
||||
concise hypothesis can help you decide how to <a href="../best-practices/write-for-action">write text message
|
||||
concise hypothesis can help you decide how to <a href="../guides/write-for-action">write text message
|
||||
content
|
||||
that provokes action</a>.
|
||||
</p>
|
||||
@@ -1,5 +1,7 @@
|
||||
{% extends "base.html" %}
|
||||
{% from "components/best-practices/circle_number.html" import circle_number %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% from "components/guides/circle_number.html" import circle_number %}
|
||||
|
||||
{% set page_title = "Establish trust" %}
|
||||
|
||||
@@ -8,7 +10,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base">Help your audience anticipate and welcome your texts.</p>
|
||||
@@ -38,7 +41,7 @@
|
||||
<li class="flex-1 width-full height-full padding-bottom-2">
|
||||
<div class="usa-card__container border-0">
|
||||
<p>To reinforce legitimacy, include these key messages in your outreach:</p>
|
||||
<ol class="best-practices-list">
|
||||
<ol class="guides-list">
|
||||
<li><b>Introduce yourself</b> – Give people time to get to know your texting communications before you need
|
||||
direct action from them</li>
|
||||
<li><b>Phone number</b> – Note the sending phone number your texts will come from</li>
|
||||
@@ -79,7 +82,7 @@
|
||||
<ul class="usa-card-group flex-1 flex-wrap padding-top-2">
|
||||
<li class="flex-1 width-full height-full padding-bottom-2">
|
||||
<div class="usa-card__container border-0">
|
||||
<ol start="7" class="best-practices-list set-two">
|
||||
<ol start="7" class="guides-list set-two">
|
||||
<li>Identify yourself in the text message. Use a consistent and familiar <b>program name</b> to precede each
|
||||
text you send.</li>
|
||||
<li>Personalize with <b>first name</b>. Through A/B testing, Code for America saw an increase in
|
||||
@@ -98,7 +101,7 @@
|
||||
<p class="sms-message-wrapper text-left">
|
||||
{{circle_number(7) }}<b>Dept. of Social Services:</b> Hi {{circle_number(8) }}<b>Julie,</b> Your Medicaid
|
||||
renewal is closing December 31, 2023. You can renew online at {{circle_number(9) }}<a
|
||||
href="https://www.application.yourstate.gov" target="_blank"
|
||||
class="use-link usa-link--external" href="https://www.application.yourstate.gov" target="_blank"
|
||||
rel="application.yourstate.gov">https://www.application.yourstate.gov</a> or {{circle_number(10) }}
|
||||
<b>call the number on the back</b> of your Medicaid card.
|
||||
</p>
|
||||
@@ -114,14 +117,14 @@
|
||||
<p>If you're sending one-way notifications, phone carriers allow a single auto-response message that will be
|
||||
generated if a recipient tries to text a response to your message. Use the auto-response to reaffirm your key
|
||||
messages around legitimacy and communicate to recipients that texts are coming from an automated system.</p>
|
||||
<ol class="best-practices-list set-three">
|
||||
<ol class="guides-list set-three">
|
||||
<li>Provide <b>a way to contact a human</b> in any auto-response text</li>
|
||||
<li>Provide <b>information on how to opt out</b> and opt back in</li>
|
||||
</ol>
|
||||
</div>
|
||||
</li>
|
||||
<li class="usa-card flex-1 usa-card--media-right width-full padding-top-3">
|
||||
<div class="usa-card__container border-0 width-full overflow-hidden best-practices">
|
||||
<div class="usa-card__container border-0 width-full overflow-hidden guides">
|
||||
<img class="width-full" src="{{ asset_url('images/phone_grey.svg') }}" role="img" alt="Phone" />
|
||||
<div class="position-absolute flex text-center padding-5 padding-top-15">
|
||||
<p class="sms-message-wrapper text-left">
|
||||
@@ -167,7 +170,7 @@
|
||||
},
|
||||
] %}
|
||||
|
||||
{% with card_contents=card_contents %}{% include "components/best-practices/cards.html" %}{%
|
||||
{% with card_contents=card_contents %}{% include "components/guides/cards.html" %}{%
|
||||
endwith %}
|
||||
<h3 class="padding-bottom-2">Prepare your team</h3>
|
||||
{% set card_contents = [
|
||||
@@ -187,7 +190,7 @@
|
||||
pages or within case management notes.",
|
||||
},
|
||||
] %}
|
||||
{% with card_contents=card_contents %}{% include "components/best-practices/cards.html" %}{%
|
||||
{% with card_contents=card_contents %}{% include "components/guides/cards.html" %}{%
|
||||
endwith %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% set page_title = "Text in multiple languages" %}
|
||||
|
||||
@@ -7,7 +8,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base"> What to know as you plan translated texts.</p>
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
|
||||
{% set page_title = "Rules and regulations" %}
|
||||
|
||||
@@ -7,7 +8,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base">Understand what is required when texting the public.</p>
|
||||
@@ -20,7 +22,7 @@
|
||||
If you do need expressed consent, consider including a pre-checked plain language opt-in (i.e. “It’s OK to text
|
||||
me.”) on
|
||||
digital forms. Be sure to ask for an up-to-date phone number and include a question about the recipient’s preferred
|
||||
language for text messages if you expect to <a href="../best-practices/multiple-languages">translate your text
|
||||
language for text messages if you expect to <a href="../guides/multiple-languages">translate your text
|
||||
messages</a> in
|
||||
languages other than English.
|
||||
</p>
|
||||
@@ -79,7 +81,7 @@
|
||||
<h3>Opting out</h3>
|
||||
<p>
|
||||
There is no policy requirement for senders to communicate opt-out options, but <a
|
||||
href="../best-practices/establish-trust#as-people-receive-texts"> including instructions in introductory and/or
|
||||
href="../guides/establish-trust#as-people-receive-texts"> including instructions in introductory and/or
|
||||
auto-response texts </a> on how to opt out and opt back in are effective ways to establish trust with your
|
||||
audience.
|
||||
</p>
|
||||
@@ -1,5 +1,6 @@
|
||||
{% extends "base.html" %}
|
||||
{% from "components/best-practices/circle_number.html" import circle_number %}
|
||||
{% import "components/nav_breadcrumb.html" as breadcrumbs %}
|
||||
{% from "components/guides/circle_number.html" import circle_number %}
|
||||
|
||||
{% set page_title = "Write texts that provoke action" %}
|
||||
|
||||
@@ -8,7 +9,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content_column_content %}
|
||||
{% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %}
|
||||
{{ breadcrumbs.breadcrumb(page_title, "Guides", "main.best_practices") }}
|
||||
|
||||
<section class="usa-prose">
|
||||
<h1>{{page_title}}</h1>
|
||||
<p class="font-sans-lg text-base"> Help your audience know what to do with the information you send.</p>
|
||||
@@ -40,11 +42,11 @@
|
||||
<li>Use a neutral, direct, and professional tone. This works better than a friendly or overly casual tone.</li>
|
||||
</ul>
|
||||
<h2>Build conditions for action</h2>
|
||||
<ul class="usa-card-group flex-1 flex-wrap padding-top-2 best-practices-flex-container">
|
||||
<ul class="usa-card-group flex-1 flex-wrap padding-top-2 guides-flex-container">
|
||||
<li class="flex-1 width-full height-full padding-bottom-2">
|
||||
<div class="usa-card__container border-0">
|
||||
<p>For example, getting a person to update their mailing address:</p>
|
||||
<ol class="best-practices-list">
|
||||
<ol class="guides-list">
|
||||
<li>Clearly state the information and the response you want the recipient to take.</li>
|
||||
<li>Point directly to where the action can be completed, not to more information.</li>
|
||||
<li>Make sure the action can be completed via mobile phone, like calling a person or going to a
|
||||
@@ -78,7 +80,8 @@
|
||||
</li>
|
||||
</ul>
|
||||
<h2>What provoking action looks like</h2>
|
||||
<p class="padding-bottom-2"><a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10002044/" target="_blank">Evidence
|
||||
<p class="padding-bottom-2"><a class="use-link usa-link--external"
|
||||
href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10002044/" target="_blank">Evidence
|
||||
shows</a> that employing
|
||||
behavioral science is an effective way to increase the
|
||||
likelihood of a recipient
|
||||
@@ -100,7 +103,7 @@
|
||||
internet services <b>that belong to you</b>.",
|
||||
},
|
||||
] %}
|
||||
{% with card_contents=card_contents, text_align='left' %}{% include "components/best-practices/cards.html" %}{%
|
||||
{% with card_contents=card_contents, text_align='left' %}{% include "components/guides/cards.html" %}{%
|
||||
endwith %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -103,6 +103,7 @@ def generate_notifications_csv(**kwargs):
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
]
|
||||
for header in original_column_headers:
|
||||
if header.lower() != "phone number":
|
||||
@@ -118,6 +119,7 @@ def generate_notifications_csv(**kwargs):
|
||||
"Carrier Response",
|
||||
"Status",
|
||||
"Time",
|
||||
"Carrier",
|
||||
]
|
||||
|
||||
yield ",".join(fieldnames) + "\n"
|
||||
@@ -140,6 +142,7 @@ def generate_notifications_csv(**kwargs):
|
||||
notification["provider_response"],
|
||||
notification["status"],
|
||||
preferred_tz_created_at,
|
||||
notification["carrier"],
|
||||
]
|
||||
for header in original_column_headers:
|
||||
if header.lower() != "phone number":
|
||||
@@ -158,6 +161,7 @@ def generate_notifications_csv(**kwargs):
|
||||
notification["provider_response"],
|
||||
notification["status"],
|
||||
preferred_tz_created_at,
|
||||
notification["carrier"],
|
||||
]
|
||||
yield Spreadsheet.from_rows([map(str, values)]).as_csv_data
|
||||
|
||||
|
||||
Reference in New Issue
Block a user