mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-23 01:19:27 -04:00
Merge branch 'main' of https://github.com/GSA/notifications-admin into 1676-individual-job-table-updates
# Conflicts: # app/templates/partials/jobs/notifications.html
This commit is contained in:
12
.ds.baseline
12
.ds.baseline
@@ -407,16 +407,6 @@
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/main/views/sign_in.py": [
|
||||
{
|
||||
"type": "Private Key",
|
||||
"filename": "app/main/views/sign_in.py",
|
||||
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
|
||||
"is_verified": false,
|
||||
"line_number": 27,
|
||||
"is_secret": false
|
||||
}
|
||||
],
|
||||
"app/templates/new/components/head.html": [
|
||||
{
|
||||
"type": "Base64 High Entropy String",
|
||||
@@ -702,5 +692,5 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"generated_at": "2024-07-11T16:37:23Z"
|
||||
"generated_at": "2024-07-24T14:13:02Z"
|
||||
}
|
||||
|
||||
@@ -327,6 +327,16 @@ td.table-empty-message {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
@media (max-width: units('desktop-lg')) {
|
||||
.table-overflow-x-auto {
|
||||
overflow-x: auto;
|
||||
table {
|
||||
min-width: 768px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Dashboard
|
||||
|
||||
.dashboard {
|
||||
@@ -376,9 +386,6 @@ td.table-empty-message {
|
||||
background-image: url(../img/material-icons/description.svg);
|
||||
}
|
||||
}
|
||||
.table-wrapper {
|
||||
overflow-x: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-table {
|
||||
|
||||
@@ -230,7 +230,12 @@ def set_up_your_profile():
|
||||
debug_msg(
|
||||
f"Added user {usr.email_address} to service {invite_data['service_id']}"
|
||||
)
|
||||
return redirect(url_for("main.show_accounts_or_dashboard"))
|
||||
# notify-admin-1766
|
||||
# redirect new users to templates area of new service instead of dashboard
|
||||
service_id = invite_data["service_id"]
|
||||
url = url_for(".service_dashboard", service_id=service_id)
|
||||
url = f"{url}/templates"
|
||||
return redirect(url)
|
||||
|
||||
elif login_gov_error:
|
||||
current_app.logger.error(f"login.gov error: {login_gov_error}")
|
||||
|
||||
@@ -29,12 +29,18 @@ from notifications_utils.url_safe_token import generate_token
|
||||
|
||||
|
||||
def _reformat_keystring(orig):
|
||||
new_keystring = orig.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||
new_keystring = new_keystring.replace("-----END PRIVATE KEY-----", "")
|
||||
private_key = "PRIVATE " # pragma: allowlist secret
|
||||
private_key = f"{private_key} KEY"
|
||||
new_keystring = orig.replace(f"-----BEGIN {private_key}-----", "")
|
||||
new_keystring = new_keystring.replace(f"-----END {private_key}-----", "")
|
||||
new_keystring = new_keystring.strip()
|
||||
new_keystring = new_keystring.replace(" ", "\n")
|
||||
new_keystring = "\n".join(
|
||||
["-----BEGIN PRIVATE KEY-----", new_keystring, "-----END PRIVATE KEY-----"]
|
||||
[
|
||||
f"-----BEGIN {private_key}-----",
|
||||
new_keystring,
|
||||
f"-----END {private_key}-----",
|
||||
]
|
||||
)
|
||||
new_keystring = f"{new_keystring}\n"
|
||||
return new_keystring
|
||||
@@ -65,7 +71,9 @@ def _get_access_token(code, state):
|
||||
response = requests.post(url, headers=headers)
|
||||
if response.json().get("access_token") is None:
|
||||
# Capture the response json here so it hopefully shows up in error reports
|
||||
current_app.logger.error(f"Error when getting access token {response.json()}")
|
||||
current_app.logger.error(
|
||||
f"Error when getting access token {response.json()} #notify-admin-1505"
|
||||
)
|
||||
raise KeyError(f"'access_token' {response.json()}")
|
||||
access_token = response.json()["access_token"]
|
||||
return access_token
|
||||
@@ -90,7 +98,9 @@ def _do_login_dot_gov():
|
||||
login_gov_error = request.args.get("error")
|
||||
|
||||
if login_gov_error:
|
||||
current_app.logger.error(f"login.gov error: {login_gov_error}")
|
||||
current_app.logger.error(
|
||||
f"login.gov error: {login_gov_error} #notify-admin-1505"
|
||||
)
|
||||
raise Exception(f"Could not login with login.gov {login_gov_error}")
|
||||
elif code and state:
|
||||
|
||||
@@ -100,12 +110,15 @@ def _do_login_dot_gov():
|
||||
user_email, user_uuid = _get_user_email_and_uuid(access_token)
|
||||
if not is_gov_user(user_email):
|
||||
current_app.logger.error(
|
||||
"invited user has a non-government email address."
|
||||
"invited user has a non-government email address. #notify-admin-1505"
|
||||
)
|
||||
flash("You must use a government email address.")
|
||||
abort(403)
|
||||
redirect_url = request.args.get("next")
|
||||
user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email)
|
||||
current_app.logger.info(
|
||||
f"Retrieved user {user['id']} from db #notify-admin-1505"
|
||||
)
|
||||
|
||||
# Check if the email needs to be revalidated
|
||||
is_fresh_email = is_less_than_days_ago(
|
||||
@@ -115,9 +128,10 @@ def _do_login_dot_gov():
|
||||
return verify_email(user, redirect_url)
|
||||
|
||||
usr = User.from_email_address(user["email_address"])
|
||||
current_app.logger.info(f"activating user {usr.id} #notify-admin-1505")
|
||||
activate_user(usr.id)
|
||||
except BaseException as be: # noqa B036
|
||||
current_app.logger.error(be)
|
||||
current_app.logger.error(f"Error signing in: {be} #notify-admin-1505 ")
|
||||
error(401)
|
||||
return redirect(url_for("main.show_accounts_or_dashboard", next=redirect_url))
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ def verify_email(token):
|
||||
current_app.config["EMAIL_EXPIRY_SECONDS"],
|
||||
)
|
||||
except SignatureExpired:
|
||||
current_app.logger.error("Email link expired #notify-admin-1505")
|
||||
flash(
|
||||
"The link in the email we sent you has expired. We've sent you a new one."
|
||||
)
|
||||
@@ -50,6 +51,9 @@ def verify_email(token):
|
||||
abort(404)
|
||||
|
||||
if user.is_active:
|
||||
current_app.logger.error(
|
||||
f"User is using an invite link but is already logged in {user.id} #notify-admin-1505"
|
||||
)
|
||||
flash("That verification link has expired.")
|
||||
return redirect(url_for("main.sign_in"))
|
||||
|
||||
@@ -59,6 +63,7 @@ def verify_email(token):
|
||||
|
||||
user.send_verify_code()
|
||||
session["user_details"] = {"email": user.email_address, "id": user.id}
|
||||
current_app.logger.info(f"Email verified for user {user.id} #notify-admin-1505")
|
||||
return redirect(url_for("main.verify"))
|
||||
|
||||
|
||||
@@ -78,5 +83,7 @@ def activate_user(user_id):
|
||||
return redirect(url_for("main.organization_dashboard", org_id=organization_id))
|
||||
else:
|
||||
activated_user = user.activate()
|
||||
current_app.logger.info(f"Activated user {user.id} #notify-admin-1505")
|
||||
activated_user.login()
|
||||
current_app.logger.info(f"Logged in user {user.id} #notify-admin-1505")
|
||||
return redirect(url_for("main.add_service", first="first"))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{% else %}
|
||||
|
||||
{% if notifications %}
|
||||
<div class="dashboard-table job-status-table">
|
||||
<div class="dashboard-table job-status-table table-overflow-x-auto">
|
||||
{% endif %}
|
||||
{% if job.still_processing %}
|
||||
<p class="bottom-gutter hint">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading, notification_status_field %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
|
||||
<div class="ajax-block-container table-wrapper" aria-labelledby='pill-selected-item'>
|
||||
<div class="dashboard-table bottom-gutter-3-2">
|
||||
<div class="ajax-block-container" aria-labelledby='pill-selected-item'>
|
||||
<div class="dashboard-table table-overflow-x-auto">
|
||||
|
||||
{% call(item, row_number) list_table(
|
||||
[notification],
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="ajax-block-container" id='pill-selected-item'>
|
||||
|
||||
{% if notifications %}
|
||||
<div class="table-wrapper">
|
||||
<div class="table-overflow-x-auto">
|
||||
<div class='dashboard-table'>
|
||||
{% endif %}
|
||||
{% call(item, row_number) list_table(
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
{% block maincolumn_content %}
|
||||
{{ page_header('Callbacks') }}
|
||||
<div class="table-wrapper">
|
||||
<div class="bottom-gutter-3-2 dashboard-table body-copy-table">
|
||||
<div class="table-overflow-x-auto">
|
||||
<div class="bottom-gutter-3-2 dashboard-table body-copy-table table-overflow-x-auto">
|
||||
{% call mapping_table(
|
||||
caption='General',
|
||||
field_headings=['Label', 'Value', 'Action'],
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="usa-table-container--scrollable" tabindex="0">
|
||||
<div class="usa-table-container--scrollable table-overflow-x-auto" tabindex="0">
|
||||
<table class="usa-table usa-table--borderless width-full">
|
||||
<caption class="font-body-lg table-heading">
|
||||
Note: Only the first 5 rows are displayed here.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading %}
|
||||
|
||||
<div class="table-wrapper">
|
||||
<div class="table-overflow-x-auto">
|
||||
<div class='dashboard-table ajax-block-container'>
|
||||
{% call(item, row_number) list_table(
|
||||
jobs,
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
No messages sent
|
||||
</p>
|
||||
{% else %}
|
||||
<div class='template-statistics-table'>
|
||||
<div class='template-statistics-table table-overflow-x-auto'>
|
||||
{% call(item, row_number) list_table(
|
||||
month.templates_used,
|
||||
caption=month.name,
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
{{ ajax_block(partials, updates_url, 'template-statistics') }}
|
||||
<h2 class="margin-top-4 margin-bottom-1">Recent Batches</h2>
|
||||
<div class="table-wrapper">
|
||||
<div class="table-overflow-x-auto">
|
||||
<table class="usa-table usa-table--borderless job-table">
|
||||
<thead class="table-field-headings">
|
||||
<tr>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div class="ajax-block-container">
|
||||
{% if template_statistics|length > 1 %}
|
||||
<div class='template-statistics-table'>
|
||||
<div class='template-statistics-table table-overflow-x-auto'>
|
||||
{% call(item, row_number) list_table(
|
||||
template_statistics,
|
||||
caption="Messages sent by template",
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
<p class="usa-body">To send a text with Notify, you need to create a reusable message template first.</p>
|
||||
<p class="usa-body">Templates let you send the same thing to lots of people, as often as you need to, without writing a new message each time.</p>
|
||||
|
||||
<h2 class="heading-medium" id="organizing-content">Organizing your content</h2>
|
||||
<p class="usa-body">You can organize your content by grouping templates, and putting them into folders.</p>
|
||||
<p class="usa-body">Set up folders within the Send message section of Notify, where you find templates. You can choose to create a Folder before or after a template is made. If you want to change a user’s ability to view or edit folders, you may control this through their individual team member permissions.</p>
|
||||
|
||||
<h2 class="heading-medium" id="personalised-messages">Personalized content</h2>
|
||||
<p class="usa-body">Notify makes it easy to send personalized messages from a single template.</p>
|
||||
<p class="usa-body">See <a class="usa-link" href="{{ url_for('.guidance_index', _anchor='personalized-content') }}">how to personalize your content</a>.</p>
|
||||
@@ -44,7 +48,6 @@
|
||||
<p class="usa-body">Notify lets you:</p>
|
||||
<ul class="list list-bullet">
|
||||
<li>set different permission levels for each team member</li>
|
||||
<li>invite team members who do not have a government email address</li>
|
||||
<li>choose who else can manage team members</li>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -162,55 +162,57 @@
|
||||
location, the flag to receive the content needs to be captured in its own column with a Yes or No (Y/N) flag.</p>
|
||||
|
||||
<h3>Example</h3>
|
||||
<table class="usa-table">
|
||||
<caption class="usa-sr-only">
|
||||
Example
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Phone number</th>
|
||||
<th scope="col">First name</th>
|
||||
<th scope="col">Last name</th>
|
||||
<th scope="col">Spanish</th>
|
||||
<th scope="col">English</th>
|
||||
<th scope="col">Date</th>
|
||||
<th scope="col">Time</th>
|
||||
<th scope="col">Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>123-456-7890</td>
|
||||
<td>Lulu</td>
|
||||
<td>Praether</td>
|
||||
<td>N</td>
|
||||
<td>Y</td>
|
||||
<td>November 2, 2023</td>
|
||||
<td>3:25</td>
|
||||
<td>123 Ford Rd.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>234-567-8901</td>
|
||||
<td>Sela</td>
|
||||
<td>Appel</td>
|
||||
<td>Y</td>
|
||||
<td>N</td>
|
||||
<td>November 2, 2023</td>
|
||||
<td>4:00</td>
|
||||
<td>123 Ford Rd.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>123-456-7890</td>
|
||||
<td>Dexter</td>
|
||||
<td>Moseley</td>
|
||||
<td>N</td>
|
||||
<td>Y</td>
|
||||
<td>November 2, 2023</td>
|
||||
<td>2:00</td>
|
||||
<td>123 Ford Rd.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-overflow-x-auto">
|
||||
<table class="usa-table">
|
||||
<caption class="usa-sr-only">
|
||||
Example
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Phone number</th>
|
||||
<th scope="col">First name</th>
|
||||
<th scope="col">Last name</th>
|
||||
<th scope="col">Spanish</th>
|
||||
<th scope="col">English</th>
|
||||
<th scope="col">Date</th>
|
||||
<th scope="col">Time</th>
|
||||
<th scope="col">Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>123-456-7890</td>
|
||||
<td>Lulu</td>
|
||||
<td>Praether</td>
|
||||
<td>N</td>
|
||||
<td>Y</td>
|
||||
<td>November 2, 2023</td>
|
||||
<td>3:25</td>
|
||||
<td>123 Ford Rd.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>234-567-8901</td>
|
||||
<td>Sela</td>
|
||||
<td>Appel</td>
|
||||
<td>Y</td>
|
||||
<td>N</td>
|
||||
<td>November 2, 2023</td>
|
||||
<td>4:00</td>
|
||||
<td>123 Ford Rd.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>123-456-7890</td>
|
||||
<td>Dexter</td>
|
||||
<td>Moseley</td>
|
||||
<td>N</td>
|
||||
<td>Y</td>
|
||||
<td>November 2, 2023</td>
|
||||
<td>2:00</td>
|
||||
<td>123 Ford Rd.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{# Preventing fraud #}
|
||||
<h2 class="padding-top-1" id="prevent-fraud">Preventing fraud</h2>
|
||||
|
||||
@@ -23,36 +23,34 @@ Inbound SMS
|
||||
<h1 class="font-body-2xl">
|
||||
Inbound SMS
|
||||
</h1>
|
||||
|
||||
<table class="usa-table usa-table--borderless inbound">
|
||||
<thread>
|
||||
<tr>
|
||||
<th>{{table_headings.field_headings[0]}}</th>
|
||||
<th>{{table_headings.field_headings[1]}}</th>
|
||||
<th>{{table_headings.field_headings[2]}}</th>
|
||||
</tr>
|
||||
</thread>
|
||||
<tbody>
|
||||
|
||||
{% for value in inbound_num_list.data: %}
|
||||
<div class="table-overflow-x-auto">
|
||||
<table class="usa-table usa-table--borderless inbound width-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{{value.number}}</td>
|
||||
<td>
|
||||
|
||||
{% if value.active %}
|
||||
Active
|
||||
{% elif not value.service.name %}
|
||||
Not used
|
||||
{% else %}
|
||||
Inactive
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('main.service_dashboard', service_id=value.service.id) }}" class="usa-link bold">{{ value.service.name }}</a>
|
||||
</td>
|
||||
<th>{{table_headings.field_headings[0]}}</th>
|
||||
<th>{{table_headings.field_headings[1]}}</th>
|
||||
<th>{{table_headings.field_headings[2]}}</th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for value in inbound_num_list.data: %}
|
||||
<tr>
|
||||
<td>{{value.number}}</td>
|
||||
<td>
|
||||
{% if value.active %}
|
||||
Active
|
||||
{% elif not value.service.name %}
|
||||
Not used
|
||||
{% else %}
|
||||
Inactive
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('main.service_dashboard', service_id=value.service.id) }}" class="usa-link bold">{{ value.service.name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{{ page_header('Invite {}'.format(user_to_invite.name if user_to_invite else 'a team member')) }}
|
||||
|
||||
<a href="#permissions">Learn more about user permissions.</a>
|
||||
{% call form_wrapper() %}
|
||||
|
||||
{% if user_to_invite %}
|
||||
@@ -36,5 +36,99 @@
|
||||
{{ page_footer('Send invitation email') }}
|
||||
|
||||
{% endcall %}
|
||||
<h2 id="permissions">Set up user permissions</h2>
|
||||
<p>Setting the right digital control is one of many aspects to keep content and information on a need to know basis. Permissions allow you to do this. Give team members access to important views related to their responsibilities.</p>
|
||||
<h3 class="site-preview-heading">Permissions</h3>
|
||||
|
||||
<div class="usa-accordion usa-accordion--bordered margin-top-1">
|
||||
<h4 class="usa-accordion__heading">
|
||||
<button
|
||||
type="button"
|
||||
class="usa-accordion__button"
|
||||
aria-expanded="true"
|
||||
aria-controls="b-a1"
|
||||
>
|
||||
See dashboard
|
||||
</button>
|
||||
</h4>
|
||||
<div id="b-a1" class="usa-accordion__content usa-prose">
|
||||
<p>Allows users to view the dashboard but not have access to any other functions on the site.
|
||||
Dashboard viewers can see: Weekly message quantity</p>
|
||||
<ul>
|
||||
<li>Message templates used</li>
|
||||
<li>Recent batches of sent messages</li>
|
||||
</ul>
|
||||
<p>This also gives access to:</p>
|
||||
<ul>
|
||||
<li>List of templates used by month</li>
|
||||
<li>Batch details with message status</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h4 class="usa-accordion__heading">
|
||||
<button
|
||||
type="button"
|
||||
class="usa-accordion__button"
|
||||
aria-expanded="false"
|
||||
aria-controls="b-a2"
|
||||
>
|
||||
Send messages
|
||||
</button>
|
||||
</h4>
|
||||
<div id="b-a2" class="usa-accordion__content usa-prose">
|
||||
<p>
|
||||
Allows users to view, select and send approved messages, but restricts users from editing templates
|
||||
and/or folders. Team members responsible for sending message batches can use templates to prepare
|
||||
and schedule texts. Actions they take in this section:
|
||||
</p>
|
||||
<ul>
|
||||
<li>View and use templates</li>
|
||||
<li>Enter personalized message field content</li>
|
||||
<li>Schedule messages for sending</li>
|
||||
<li>Send messages</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h4 class="usa-accordion__heading">
|
||||
<button
|
||||
type="button"
|
||||
class="usa-accordion__button"
|
||||
aria-expanded="false"
|
||||
aria-controls="b-a3"
|
||||
>
|
||||
Add and edit templates
|
||||
</button>
|
||||
</h4>
|
||||
<div id="b-a3" class="usa-accordion__content usa-prose">
|
||||
<p>
|
||||
Allows users to view, create or edit, and more or delete templates and folders. They will set up real
|
||||
messages, but are restricted from uploading data or sending or seeing previous versions. Some actions
|
||||
they can take:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Create a new template</li>
|
||||
<li>Create a new folder</li>
|
||||
<li>Move (or organize) folders and templates</li>
|
||||
<li>Delete templates and/or folders</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h4 class="usa-accordion__heading">
|
||||
<button
|
||||
type="button"
|
||||
class="usa-accordion__button"
|
||||
aria-expanded="false"
|
||||
aria-controls="b-a4"
|
||||
>
|
||||
Manage settings and team
|
||||
</button>
|
||||
</h4>
|
||||
<div id="b-a4" class="usa-accordion__content usa-prose">
|
||||
<p>Leads with service management responsibility may do so in Settings. Managed within Settings:</p>
|
||||
<ul>
|
||||
<li>Change service name</li>
|
||||
<li>Invite team members</li>
|
||||
<li>Remove unnecessary team members</li>
|
||||
<li>Turn off the ability to send text messages</li>
|
||||
<li>Turn off the ability to send service name with text message</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<p>Notify cannot tell you if your users open an email or click on the links in an email. We do not track open rates and click-throughs because there are privacy issues. Tracking emails without asking permission from users could breach General Data Protection Regulations (GDPR).</p> -->
|
||||
|
||||
<h2 id="text-message-statuses" class="heading-medium">Text messages</h2>
|
||||
<div class="margin-bottom-8">
|
||||
<div class="margin-bottom-8 table-overflow-x-auto">
|
||||
{% call mapping_table(
|
||||
caption='Message statuses – text messages',
|
||||
field_headings=['Status', 'Description'],
|
||||
|
||||
@@ -44,33 +44,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-wrapper">
|
||||
<div class="dashboard-table">
|
||||
{% call(item, row_number) list_table(
|
||||
notifications_by_type|reverse,
|
||||
caption='Messages sent since May 2023',
|
||||
caption_visible=False,
|
||||
field_headings=[
|
||||
'Date',
|
||||
99|message_count_noun('email')|capitalize,
|
||||
99|message_count_noun('sms')|capitalize,
|
||||
],
|
||||
empty_message='No data to show'
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.date | format_date_normal }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ item.emails|format_thousands }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ item.sms|format_thousands }}
|
||||
{% endcall %}
|
||||
<div class="dashboard-table table-overflow-x-auto">
|
||||
{% call(item, row_number) list_table(
|
||||
notifications_by_type|reverse,
|
||||
caption='Messages sent since May 2023',
|
||||
caption_visible=False,
|
||||
field_headings=[
|
||||
'Date',
|
||||
99|message_count_noun('email')|capitalize,
|
||||
99|message_count_noun('sms')|capitalize,
|
||||
],
|
||||
empty_message='No data to show'
|
||||
) %}
|
||||
{% call field() %}
|
||||
{{ item.date | format_date_normal }}
|
||||
{% endcall %}
|
||||
<p class="table-show-more-link">
|
||||
Only showing the last {{ notifications_by_type|length }} days
|
||||
</p>
|
||||
</div>
|
||||
{% call field() %}
|
||||
{{ item.emails|format_thousands }}
|
||||
{% endcall %}
|
||||
{% call field() %}
|
||||
{{ item.sms|format_thousands }}
|
||||
{% endcall %}
|
||||
{% endcall %}
|
||||
<p class="table-show-more-link">
|
||||
Only showing the last {{ notifications_by_type|length }} days
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 class="govuk-heading-m">
|
||||
@@ -84,7 +82,7 @@
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<div class="table-overflow-x-auto">
|
||||
<div class="dashboard-table">
|
||||
{% call(item, row_number) list_table(
|
||||
processing_time | reverse,
|
||||
@@ -124,7 +122,7 @@
|
||||
<span class="usa-sr-only">using Notify.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-wrapper">
|
||||
<div class="table-overflow-x-auto">
|
||||
<div class="dashboard-table">
|
||||
{% call(item, row_number) list_table(
|
||||
organizations_using_notify,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="grid-row margin-bottom-10">
|
||||
<div class="tablet:grid-col-3 margin-top-4">
|
||||
<div class="tablet:grid-col-2 margin-top-4">
|
||||
<nav class="navigation">
|
||||
<ul class="usa-sidenav">
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="grid-col-9 tablet:grid-col-9 padding-left-4 sub-content">
|
||||
<div class="grid-col-10 tablet:grid-col-10 padding-left-4 sub-content">
|
||||
{% block backLink %}{% endblock %}
|
||||
<main id="main-content" role="main">
|
||||
{% block content %}
|
||||
|
||||
@@ -13,26 +13,26 @@
|
||||
Email complaints
|
||||
</h1>
|
||||
|
||||
<div class="table-overflow-x-auto">
|
||||
{% call(item, row_number) list_table(
|
||||
complaints,
|
||||
caption="Complaints",
|
||||
caption_visible=False,
|
||||
empty_message='No complaints',
|
||||
field_headings=['Notification Id', 'Service', 'Complaint type', 'Complaint Date'],
|
||||
field_headings_visible=True
|
||||
) %}
|
||||
|
||||
{% call(item, row_number) list_table(
|
||||
complaints,
|
||||
caption="Complaints",
|
||||
caption_visible=False,
|
||||
empty_message='No complaints',
|
||||
field_headings=['Notification Id', 'Service', 'Complaint type', 'Complaint Date'],
|
||||
field_headings_visible=True
|
||||
) %}
|
||||
{{ link_field(item.notification_id, url_for('main.view_notification', service_id=item.service_id, notification_id=item.notification_id)) }}
|
||||
|
||||
{{ link_field(item.notification_id, url_for('main.view_notification', service_id=item.service_id, notification_id=item.notification_id)) }}
|
||||
{{ link_field(item.service_name, url_for('main.service_dashboard', service_id=item.service_id)) }}
|
||||
|
||||
{{ link_field(item.service_name, url_for('main.service_dashboard', service_id=item.service_id)) }}
|
||||
{{ text_field(item.complaint_type) }}
|
||||
|
||||
{{ text_field(item.complaint_type) }}
|
||||
|
||||
{{ text_field(item.complaint_date|format_datetime_table if item.complaint_date else None) }}
|
||||
|
||||
{% endcall %}
|
||||
{{ text_field(item.complaint_date|format_datetime_table if item.complaint_date else None) }}
|
||||
|
||||
{% endcall %}
|
||||
</div>
|
||||
{{ previous_next_navigation(prev_page, next_page) }}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
{% from "components/components/details/macro.njk" import usaDetails %}
|
||||
|
||||
{% macro services_table(services, caption) %}
|
||||
<div class="table-overflow-x-auto">
|
||||
{% call(item, row_number) mapping_table(
|
||||
caption=caption,
|
||||
caption_visible=False,
|
||||
@@ -48,6 +49,7 @@
|
||||
{% endfor %}
|
||||
|
||||
{% endcall %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ part.</p>
|
||||
|
||||
<h4>Calculation of message parts without special characters</h4>
|
||||
|
||||
<div class="bottom-gutter-3-2">
|
||||
<div class="table-overflow-x-auto">
|
||||
{% call mapping_table(
|
||||
caption='Text message pricing',
|
||||
field_headings=['Message length', 'Charge'],
|
||||
@@ -86,7 +86,7 @@ recipient’s preferred language, but we are aware that, rarely, a phone carrier
|
||||
to be calculated as detailed below.<p>
|
||||
<h4>Calculation of message parts with special characters or non-romanized scripts</h4>
|
||||
{% set accentedChars %}
|
||||
<div class="bottom-gutter-3-2">
|
||||
<div class="table-overflow-x-auto">
|
||||
{% call mapping_table(
|
||||
caption='Accented characters that affect text message charges',
|
||||
field_headings=['Character', 'Description'],
|
||||
@@ -151,7 +151,7 @@ to be calculated as detailed below.<p>
|
||||
"html": accentedChars
|
||||
}) }}
|
||||
|
||||
<div class="bottom-gutter-3-2">
|
||||
<div class="table-overflow-x-auto">
|
||||
{% call mapping_table(
|
||||
caption='Pricing for text messages containing accented characters that affect the charges',
|
||||
field_headings=['Message length', 'Charge'],
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<h1 class="font-body-lg">Settings</h1>
|
||||
|
||||
<div class="bottom-gutter-3-2 settings-table body-copy-table">
|
||||
<div class="bottom-gutter-3-2 settings-table body-copy-table table-overflow-x-auto">
|
||||
|
||||
{% call mapping_table(
|
||||
caption='General',
|
||||
|
||||
@@ -20,7 +20,7 @@ Notify.gov
|
||||
<div class="desktop:grid-col-7 tablet:grid-col-12">
|
||||
<h1 class="font-serif-2xl usa-hero__heading">Reach people where they are with government-powered text messages</h1>
|
||||
<p class="font-sans-lg">Notify.gov is a text message service that helps federal, state, local, tribal and territorial governments more effectively communicate with the people they serve.</p>
|
||||
<div class="usa-button-group margin-bottom-5">
|
||||
<div class="usa-button-group margin-bottom-5 flex-align-center">
|
||||
<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>
|
||||
if you are an existing pilot partner
|
||||
|
||||
@@ -70,8 +70,7 @@
|
||||
</div> #}
|
||||
|
||||
{% if months %}
|
||||
<div class="table-wrapper">
|
||||
<div class="dashboard-table usage-table body-copy-table margin-top-4">
|
||||
<div class="dashboard-table usage-table body-copy-table table-overflow-x-auto margin-top-4">
|
||||
{% call(item, row_index) list_table(
|
||||
months,
|
||||
caption="Total spend",
|
||||
@@ -122,7 +121,6 @@
|
||||
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
{% block orgNavBreadcrumb %}{% include "/new/components/org_nav_breadcrumb.html" %}{% endblock %}
|
||||
{% endif %}
|
||||
<div class="grid-row margin-top-5">
|
||||
<div class="tablet:grid-col-3">
|
||||
<div class="tablet:grid-col-2">
|
||||
{% block sideNavigation %}
|
||||
{% if current_org.name %}
|
||||
{% include "/new/components/org_nav.html" %}
|
||||
@@ -44,7 +44,7 @@
|
||||
#}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="tablet:grid-col-9 tablet:padding-left-4">
|
||||
<div class="tablet:grid-col-10 tablet:padding-left-4">
|
||||
{% block beforeContent %}
|
||||
{% block backLink %}{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -34,12 +34,6 @@ module "logo_upload_bucket" {
|
||||
name = "${local.app_name}-logo-upload-bucket-${local.env}"
|
||||
}
|
||||
|
||||
# ##########################################################################
|
||||
# The following lines need to be commented out for the initial `terraform apply`
|
||||
# It can be re-enabled after:
|
||||
# 1) the api app has first been deployed
|
||||
# 2) the admin app has first been deployed
|
||||
###########################################################################
|
||||
module "api_network_route" {
|
||||
source = "../shared/container_networking"
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
locals {
|
||||
cf_org_name = "gsa-tts-benefits-studio"
|
||||
cf_space_name = "notify-local-dev"
|
||||
recursive_delete = true
|
||||
key_name = "${var.username}-admin-dev-key"
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,6 @@ module "logo_upload_bucket" {
|
||||
name = "${local.app_name}-logo-upload-bucket-${local.env}"
|
||||
}
|
||||
|
||||
# ##########################################################################
|
||||
# The following lines need to be commented out for the initial `terraform apply`
|
||||
# It can be re-enabled after:
|
||||
# 1) the api app has first been deployed
|
||||
# 2) the admin app has first been deployed
|
||||
###########################################################################
|
||||
module "api_network_route" {
|
||||
source = "../shared/container_networking"
|
||||
|
||||
@@ -50,22 +44,25 @@ module "api_network_route" {
|
||||
}
|
||||
|
||||
# ##########################################################################
|
||||
# The following lines need to be commented out for the initial `terraform apply`
|
||||
# It can be re-enabled after:
|
||||
# 1) the app has first been deployed
|
||||
# 2) the route has been manually created by an OrgManager:
|
||||
# This governs the name of our main website. Because domain names are unique,
|
||||
# it only lives here in this one location in production. Resulting problem:
|
||||
# it is hard to test. Create a temporary, similar code block (with a different
|
||||
# subdomain) in Sandbox, test your changes there, and bring them here.
|
||||
#
|
||||
# Dependencies:
|
||||
# 1) an app named notify-admin-production in Cloud.gov
|
||||
# 2) this route, manually created by an OrgManager:
|
||||
# `cf create-domain gsa-tts-benefits-studio beta.notify.gov`
|
||||
# 3) the acme-challenge CNAME record must be created
|
||||
# 3) the acme-challenge CNAME record
|
||||
# https://cloud.gov/docs/services/external-domain-service/#how-to-create-an-instance-of-this-service
|
||||
###########################################################################
|
||||
module "domain" {
|
||||
source = "github.com/18f/terraform-cloudgov//domain?ref=v0.7.1" # TODO: upgrade this
|
||||
source = "github.com/GSA-TTS/terraform-cloudgov//domain?ref=v1.0.0"
|
||||
|
||||
cf_org_name = local.cf_org_name
|
||||
cf_space_name = local.cf_space_name
|
||||
app_name_or_id = "${local.app_name}-${local.env}"
|
||||
name = "${local.app_name}-domain-${local.env}"
|
||||
recursive_delete = false
|
||||
cdn_plan_name = "domain"
|
||||
domain_name = "beta.notify.gov"
|
||||
}
|
||||
|
||||
@@ -34,17 +34,11 @@ module "logo_upload_bucket" {
|
||||
name = "${local.app_name}-logo-upload-bucket-${local.env}"
|
||||
}
|
||||
|
||||
# ##########################################################################
|
||||
# The following lines need to be commented out for the initial `terraform apply`
|
||||
# It can be re-enabled after:
|
||||
# 1) the api app has first been deployed
|
||||
# 2) the admin app has first been deployed
|
||||
###########################################################################
|
||||
# module "api_network_route" {
|
||||
# source = "../shared/container_networking"
|
||||
module "api_network_route" { # API and Admin apps must both exist in Cloud
|
||||
source = "../shared/container_networking"
|
||||
|
||||
# cf_org_name = local.cf_org_name
|
||||
# cf_space_name = local.cf_space_name
|
||||
# source_app_name = "${local.app_name}-${local.env}"
|
||||
# destination_app_name = "notify-api-${local.env}"
|
||||
# }
|
||||
cf_org_name = local.cf_org_name
|
||||
cf_space_name = local.cf_space_name
|
||||
source_app_name = "${local.app_name}-${local.env}"
|
||||
destination_app_name = "notify-api-${local.env}"
|
||||
}
|
||||
|
||||
@@ -34,12 +34,6 @@ module "logo_upload_bucket" {
|
||||
name = "${local.app_name}-logo-upload-bucket-${local.env}"
|
||||
}
|
||||
|
||||
# ##########################################################################
|
||||
# The following lines need to be commented out for the initial `terraform apply`
|
||||
# It can be re-enabled after:
|
||||
# 1) the api app has first been deployed
|
||||
# 2) the admin app has first been deployed
|
||||
###########################################################################
|
||||
module "api_network_route" {
|
||||
source = "../shared/container_networking"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user