Merge branch 'master' of https://github.com/alphagov/notifications-admin into make-content-links-in-notify-consistent

This commit is contained in:
chrisw
2018-01-05 14:50:05 +00:00
70 changed files with 1792 additions and 1226 deletions

View File

@@ -41,11 +41,12 @@
' form-control-error' if field.errors else ''
)
%}
{{ field(**{
'class': field_class,
'data-module': 'highlight-tags' if highlight_tags else '',
'rows': rows|string
}) }}
{{ field(
class=field_class,
data_module='highlight-tags' if highlight_tags else '',
rows=rows|string,
**kwargs
) }}
{% if suffix %}
<span>{{ suffix }}</span>
{% endif %}

View File

@@ -31,7 +31,7 @@
</p>
{% elif notifications %}
<p class="bottom-gutter">
<a href="{{ download_link }}" download="download" class="heading-small">Download this report</a>
<a href="{{ download_link }}" download class="heading-small">Download this report</a>
&emsp;
<span id="time-left">{{ time_left }}</span>
</p>

View File

@@ -0,0 +1,33 @@
{% extends "withnav_template.html" %}
{% from "components/textbox.html" import textbox %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/table.html" import mapping_table, row, text_field, edit_field, optional_text_field %}
{% block service_page_title %}
Callbacks
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Callbacks</h1>
<div class="bottom-gutter-3-2 dashboard-table body-copy-table">
{% call mapping_table(
caption='General',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False,
caption_visible=False
) %}
{% call row() %}
{{ text_field('Callbacks for delivery receipts') }}
{{ optional_text_field(delivery_status_callback) }}
{{ edit_field('Change', url_for('.delivery_status_callback', service_id=current_service.id)) }}
{% endcall %}
{% call row() %}
{{ text_field('Callbacks for received text messages') }}
{{ optional_text_field(received_text_messages_callback) }}
{{ edit_field('Change', url_for('.received_text_messages_callback', service_id=current_service.id)) }}
{% endcall %}
{% endcall %}
</div>
{% endblock %}

View File

@@ -3,32 +3,33 @@
{% from "components/page-footer.html" import page_footer %}
{% block service_page_title %}
Callback URL
Callbacks for delivery receipts
{% endblock %}
{% block maincolumn_content %}
<div class="grid-row">
<div class="column-five-sixths">
<h1 class="heading-large">Callback URL for received text messages</h1>
<h1 class="heading-large">Callbacks for delivery receipts</h1>
<p>
Text messages you receive can be forwarded to your systems with our callback feature.
See our <a href="{{ url_for('.callbacks') }}">documentation on the format of the callback</a>.
When you send an email or text message, we can tell you if Notify was able to deliver it.
Check the <a href="{{ url_for('.callbacks') }}"> callback documentation </a> for more information.
</p>
<form method="post">
{{ textbox(
form.url,
width='2-3',
hint='Valid https URL'
width='1-1',
hint='Must start with https://'
) }}
{{ textbox(
form.bearer_token,
width='2-3',
hint='At least 10 characters'
width='1-1',
hint='At least 10 characters',
autocomplete='new-password'
) }}
{{ page_footer(
'Save',
back_link=url_for('.service_settings', service_id=current_service.id),
back_link=url_for(back_link, service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>

View File

@@ -0,0 +1,39 @@
{% extends "withnav_template.html" %}
{% from "components/textbox.html" import textbox %}
{% from "components/page-footer.html" import page_footer %}
{% block service_page_title %}
Callbacks for received text messages
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Callbacks for received text messages</h1>
<div class="grid-row">
<div class="column-five-sixths">
<p>
When you receive a text message in Notify, we can forward it to your system.
Check the <a href="{{ url_for('.callbacks') }}"> callback documentation </a> for more information.
</p>
<form method="post">
{{ textbox(
form.url,
width='1-1',
hint='Must start with https://'
) }}
{{ textbox(
form.bearer_token,
width='1-1',
hint='At least 10 characters',
autocomplete='new-password'
) }}
{{ page_footer(
'Save',
back_link=url_for('.api_callbacks', service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>
</div>
</div>
{% endblock %}

View File

@@ -21,7 +21,7 @@
<a class="pill-separate-item" href="{{ url_for('.whitelist', service_id=current_service.id) }}">Whitelist</a>
</div>
<div class="column-one-third">
<a class="pill-separate-item" href="{{ url_for('.api_documentation', service_id=current_service.id) }}">Documentation</a>
<a class="pill-separate-item" href="{{ url_for(callbacks_link, service_id=current_service.id) }}">Callbacks</a>
</div>
</nav>

View File

@@ -2,41 +2,49 @@
{% extends "withoutnav_template.html" %}
{% block per_page_title %}
Callbacks for received text messages
Callback documentation
{% endblock %}
{% block maincolumn_content %}
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-large">Callbacks for received text messages</h1>
<p>
Text messages you receive can be forwarded to a URL that you specify, using our callback feature.
</p>
<h1 class="heading-large">Callback documentation</h1>
<p>A callback lets you receive messages from Notify to a URL you choose.</p>
<p>Youll need to provide a bearer token, for security. Well add this to the authorisation header of the callback request.</p>
<p>The callback message is in JSON.</p>
<p>
Messages are forwarded as they are received.
</p>
<p>
To protect your service, we require you to provide a bearer token. We put this token in the authorisation header of the callback requests.
</p>
<p>
Once you have receive text messages enabled, you can set up your callback on the settings page of your service.
</p>
<p>
If you dont have receive text messages enabled for your service, <a href="{{ url_for('.support') }}">get in touch</a> and we can turn it on for you.
</p>
<h2 class="heading-medium">Format of the callback</h2>
<p>
The format of the callback message you receive is JSON.
</p>
<h2 class="heading-medium">Email and text message delivery receipts</h2>
<p>When you send an email or text message through Notify, we can send a receipt to your callback URL to tell you if we were able to deliver it or not.</p>
<div class="bottom-gutter-3-2">
{% call mapping_table(
caption='Callback message format',
field_headings=['Key', 'Description', 'Format'],
field_headings_visible=True,
caption_visible=False
) %}
{% for key, description, format in [
('id', 'Notifys id for the status receipts', 'UUID'),
('reference', 'The reference sent by the service', '12345678'),
('to', 'The email address of the recipient', 'hello@gov.uk'),
('status', 'The status of the notification', 'delivered | permanent-failure | temporary-failure | technical-failure'),
('created_at', 'The time the service sent the request', '2017-05-14T12:15:30.000000Z'),
('completed_at', 'The last time the status was updated', '2017-05-14T12:15:30.000000Z'),
('sent_at', 'The time the notification was sent', '2017-05-14T12:15:30.000000Z or nil'),
('notification_type', 'The notification type', 'email | sms | letter')
] %}
{% call row() %}
{% call row_heading() %} {{ key }} {% endcall %}
{{ text_field(description) }}
{{ text_field(format) }}
{% endcall %}
{% endfor %}
{% endcall %}
</div>
<h2 class="heading-medium">Text messages you receive</h2>
<p>If your service receives text messages in Notify, we can forward them to your callback URL as soon as they arrive.</p>
<div class="bottom-gutter-3-2">
{% call mapping_table(
caption='Callback message format',
@@ -59,5 +67,4 @@
{% endfor %}
{% endcall %}
</div>
{% endblock %}

View File

@@ -38,12 +38,18 @@
<h1 class='banner-title' data-module="track-error" data-error-type="No rows" data-error-label="{{ upload_id }}">
Your file is missing some rows
</h1>
<p>
It needs at least one row of data, and {{ recipients.missing_column_headers | sort() | formatted_list(
prefix='a column called',
prefix_plural='columns called'
) }}.
</p>
{% if recipients.missing_column_headers %}
<p>
It needs at least one row of data, and {{ recipients.missing_column_headers | sort() | formatted_list(
prefix='a column called',
prefix_plural='columns called'
) }}.
</p>
{% else %}
<p>
It needs at least one row of data.
</p>
{% endif %}
{% elif not recipients.has_recipient_columns %}
@@ -108,54 +114,58 @@
{% endcall %}
</div>
<div class="bottom-gutter-3-2">
{% if request.args.from_test %}
<a href="{{ back_link }}" class="page-footer-back-link">Back</a>
{% else %}
{{file_upload(form.file, button_text='Re-upload your file')}}
{% endif %}
<div class="js-stick-at-top-when-scrolling">
<div class="form-group">
{% if request.args.from_test %}
<a href="{{ back_link }}" class="page-footer-back-link">Back</a>
{% else %}
{{file_upload(form.file, button_text='Re-upload your file')}}
{% endif %}
</div>
<a href="#content" class="back-to-top-link">Back to top</a>
</div>
{% if not request.args.from_test %}
<h2 class="heading-medium" id="{{ file_contents_header_id }}">{{ original_file_name }}</h2>
{% call(item, row_number) list_table(
recipients.initial_annotated_rows_with_errors if row_errors and not recipients.missing_column_headers else recipients.initial_annotated_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="visually-hidden">Row in file</span><span aria-hidden="true">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span class="{% if item.index in recipients.rows_with_errors %}table-field-error{% endif %}">
{{ item.index + 2 }}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item['columns'][column].error and not recipients.missing_column_headers %}
{% call field() %}
<span>
<span class="table-field-error-label">{{ item['columns'][column].error }}</span>
{{ item['columns'][column].data if item['columns'][column].data != None }}
</span>
{% endcall %}
{% elif item['columns'][column].ignore %}
{{ text_field(item['columns'][column].data or '', status='default') }}
{% else %}
{{ text_field(item['columns'][column].data or '') }}
{% endif %}
{% endfor %}
{% if item['columns'].get(None) %}
{% for column in item['columns'][None].data %}
{{ text_field(column, status='default') }}
<div class="fullscreen-content" data-module="fullscreen-table">
{% call(item, row_number) list_table(
recipients.initial_annotated_rows_with_errors if row_errors and not recipients.missing_column_headers else recipients.initial_annotated_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="visually-hidden">Row in file</span><span aria-hidden="true">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span>
{{ item.index + 2 }}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item['columns'][column].error and not recipients.missing_column_headers %}
{% call field() %}
<span>
<span class="table-field-error-label">{{ item['columns'][column].error }}</span>
{{ item['columns'][column].data if item['columns'][column].data != None }}
</span>
{% endcall %}
{% elif item['columns'][column].ignore %}
{{ text_field(item['columns'][column].data or '', status='default') }}
{% else %}
{{ text_field(item['columns'][column].data or '') }}
{% endif %}
{% endfor %}
{% endif %}
{% endcall %}
{% endif %}
{% if item['columns'].get(None) %}
{% for column in item['columns'][None].data %}
{{ text_field(column, status='default') }}
{% endfor %}
{% endif %}
{% endcall %}
{% endif %}
</div>
{% if recipients.too_many_rows %}
<p class="table-show-more-link">

View File

@@ -39,7 +39,7 @@
{% if template.template_type != 'letter' or not request.args.from_test %}
<input type="submit" class="button" value="Send {{ count_of_recipients }} {{ message_count_label(count_of_recipients, template.template_type, suffix='') }}" />
{% else %}
<a href="{{ url_for('main.check_messages_preview', service_id=current_service.id, template_type=template.template_type, upload_id=upload_id, filetype='pdf') }}" download="download" class="button">Download as a printable PDF</a>
<a href="{{ url_for('main.check_messages_preview', service_id=current_service.id, template_type=template.template_type, upload_id=upload_id, filetype='pdf') }}" download class="button">Download as a printable PDF</a>
{% endif %}
<a href="{{ back_link }}" class="page-footer-back-link">Back</a>
</form>
@@ -49,42 +49,40 @@
<h2 class="heading-medium" id="{{ file_contents_header_id }}">{{ original_file_name }}</h2>
{% call(item, row_number) list_table(
recipients.initial_annotated_rows_with_errors if row_errors and not recipients.missing_column_headers else recipients.initial_annotated_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="visually-hidden">Row in file</span><span aria-hidden="true">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span class="{% if item.index in recipients.rows_with_errors %}table-field-error{% endif %}">
{{ item.index + 2 }}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item['columns'][column].ignore %}
{{ text_field(item['columns'][column].data or '', status='default') }}
{% else %}
{{ text_field(item['columns'][column].data or '') }}
{% endif %}
{% endfor %}
{% if item['columns'].get(None) %}
{% for column in item['columns'][None].data %}
{{ text_field(column, status='default') }}
<div class="fullscreen-content" data-module="fullscreen-table">
{% call(item, row_number) list_table(
recipients.initial_annotated_rows_with_errors if row_errors and not recipients.missing_column_headers else recipients.initial_annotated_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="visually-hidden">Row in file</span><span aria-hidden="true">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span class="{% if item.index in recipients.rows_with_errors %}table-field-error{% endif %}">
{{ item.index + 2 }}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item['columns'][column].ignore %}
{{ text_field(item['columns'][column].data or '', status='default') }}
{% else %}
{{ text_field(item['columns'][column].data or '') }}
{% endif %}
{% endfor %}
{% endif %}
{% endcall %}
{% if item['columns'].get(None) %}
{% for column in item['columns'][None].data %}
{{ text_field(column, status='default') }}
{% endfor %}
{% endif %}
{% endcall %}
</div>
{% endif %}
{% if count_of_displayed_recipients < count_of_recipients %}
<p class="table-show-more-link">
{% if row_errors and not recipients.missing_column_headers %}
Only showing the first {{ count_of_displayed_recipients }} rows with errors
{% else %}
Only showing the first {{ count_of_displayed_recipients }} rows
{% endif %}
Only showing the first {{ count_of_displayed_recipients }} rows
</p>
{% endif %}

View File

@@ -19,7 +19,7 @@
{% block maincolumn_content %}
<div class="bottom-gutter">
<div class="bottom-gutter-1-2">
{% call banner_wrapper(type='dangerous') %}
{% if row_errors|length == 1 %}
<h1 class='banner-title' data-module="track-error" data-error-type="Bad rows" data-error-label="{{ upload_id }}">
@@ -45,44 +45,48 @@
{% endcall %}
</div>
<div class="bottom-gutter-3-2">
{{ file_upload(form.file, button_text='Re-upload your file') }}
<div class="js-stick-at-top-when-scrolling">
<div class="form-group">
{{ file_upload(form.file, button_text='Re-upload your file') }}
</div>
<a href="#content" class="back-to-top-link">Back to top</a>
</div>
{% call(item, row_number) list_table(
recipients.initial_annotated_rows_with_errors if row_errors and not recipients.missing_column_headers else recipients.initial_annotated_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="visually-hidden">Row in file</span><span aria-hidden="true" class="table-field-invisible-error">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span class="{% if item.index in recipients.rows_with_errors %}table-field-error{% endif %}">
{{ item.index + 2 }}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item['columns'][column].error and not recipients.missing_column_headers %}
{% call field() %}
<span>
<span class="table-field-error-label">{{ item['columns'][column].error }}</span>
{{ item['columns'][column].data if item['columns'][column].data != None }}
</span>
{% endcall %}
{% elif item['columns'][column].ignore %}
{{ text_field(item['columns'][column].data or '', status='default') }}
{% else %}
{{ text_field(item['columns'][column].data or '') }}
{% endif %}
{% endfor %}
{% if item['columns'].get(None) %}
{% for column in item['columns'][None].data %}
{{ text_field(column, status='default') }}
<div class="fullscreen-content" data-module="fullscreen-table">
{% call(item, row_number) list_table(
recipients.initial_annotated_rows_with_errors if row_errors and not recipients.missing_column_headers else recipients.initial_annotated_rows,
caption=original_file_name,
caption_visible=False,
field_headings=[
'<span class="visually-hidden">Row in file</span><span aria-hidden="true" class="table-field-invisible-error">1</span>'|safe
] + recipients.column_headers
) %}
{% call index_field() %}
<span class="{% if item.index in recipients.rows_with_errors %}table-field-error{% endif %}">
{{ item.index + 2 }}
</span>
{% endcall %}
{% for column in recipients.column_headers %}
{% if item['columns'][column].error and not recipients.missing_column_headers %}
{% call field() %}
<span>
<span class="table-field-error-label">{{ item['columns'][column].error }}</span>
{{ item['columns'][column].data if item['columns'][column].data != None }}
</span>
{% endcall %}
{% elif item['columns'][column].ignore %}
{{ text_field(item['columns'][column].data or '', status='default') }}
{% else %}
{{ text_field(item['columns'][column].data or '') }}
{% endif %}
{% endfor %}
{% endif %}
{% endcall %}
{% if item['columns'].get(None) %}
{% for column in item['columns'][None].data %}
{{ text_field(column, status='default') }}
{% endfor %}
{% endif %}
{% endcall %}
</div>
{% if count_of_displayed_recipients < count_of_recipients %}
<p class="table-show-more-link">
{% if row_errors and not recipients.missing_column_headers %}

View File

@@ -4,7 +4,7 @@
<div class="ajax-block-container">
{% if messages %}
<p class="bottom-gutter-2-3 top-gutter-2-3">
<a href="{{ url_for('.inbox_download', service_id=current_service.id) }}" download="download" class="heading-small">Download these messages</a>
<a href="{{ url_for('.inbox_download', service_id=current_service.id) }}" download class="heading-small">Download these messages</a>
</p>
{% endif %}
{% call(item, row_number) list_table(

View File

@@ -53,7 +53,7 @@
{% if template.template_type != 'letter' or not request.args.from_test %}
<input type="submit" class="button" value="Send 1 {{ message_count_label(1, template.template_type, suffix='') }}" />
{% else %}
<a href="{{ url_for('main.check_messages_preview', service_id=current_service.id, template_type=template.template_type, upload_id=upload_id, filetype='pdf') }}" download="download" class="button">Download as a printable PDF</a>
<a href="{{ url_for('main.check_messages_preview', service_id=current_service.id, template_type=template.template_type, upload_id=upload_id, filetype='pdf') }}" download class="button">Download as a printable PDF</a>
{% endif %}
{% endif %}
<a href="{{ back_link }}" class="page-footer-back-link">Back</a>

View File

@@ -35,7 +35,7 @@
Estimated delivery date: {{ estimated_letter_delivery_date|string|format_date_short }}
</p>
<p class="bottom-gutter">
<a href="{{ url_for('main.view_letter_notification_as_preview', service_id=current_service.id, notification_id=notification_id, filetype='pdf') }}" download="download">Download as a PDF</a>
<a href="{{ url_for('main.view_letter_notification_as_preview', service_id=current_service.id, notification_id=notification_id, filetype='pdf') }}" download>Download as a PDF</a>
</p>
{% endif %}

View File

@@ -40,7 +40,7 @@
{% endcall %}
</div>
<p class="table-show-more-link">
<a href="{{ url_for('.get_example_csv', service_id=current_service.id, template_id=template.id) }}">Download this example</a>
<a href="{{ url_for('.get_example_csv', service_id=current_service.id, template_id=template.id) }}" download>Download this example</a>
</p>
<h2 class="heading-medium">Your file will populate this template ({{ template.name }})</h2>

View File

@@ -120,14 +120,6 @@
{{ edit_field('Change', url_for('.service_set_inbound_sms', service_id=current_service.id)) }}
{% endcall %}
{% if can_receive_inbound %}
{% call row() %}
{{ text_field('Callback URL for received text messages') }}
{{ optional_text_field(inbound_api_url) }}
{{ edit_field('Change', url_for('.service_set_inbound_api', service_id=current_service.id)) }}
{% endcall %}
{% endif %}
{% endif %}
{% endcall %}

View File

@@ -29,7 +29,7 @@
{% endif %}
{{ page_footer(
'Add',
back_link=url_for('.service_letter_contact_details', service_id=current_service.id),
back_link=None if request.args.get('from_template') else url_for('.service_letter_contact_details', service_id=current_service.id),
back_link_text='Back'
) }}
</form>

View File

@@ -120,12 +120,12 @@
<div class="grid-row bottom-gutter">
<div class="column-half">
<h3 class="visually-hidden">Services</h3>
<div class="product-page-big-number">115</div>
<div class="product-page-big-number">131</div>
services
</div>
<div class="column-half">
<h3 class="visually-hidden">Organisations</h3>
<div class="product-page-big-number">48</div>
<div class="product-page-big-number">55</div>
organisations
</div>
</div>

View File

@@ -35,7 +35,11 @@
<div class="column-whole template-container">
{% if current_user.has_permissions(permissions=['manage_templates'], admin_override=True) and template.template_type == 'letter' %}
<a href="{{ url_for(".edit_service_template", service_id=current_service.id, template_id=template.id) }}" class="edit-template-link-letter-body">Edit</a>
<a href="{{ url_for(".service_edit_letter_contact", service_id=current_service.id, letter_contact_id=default_letter_contact_block_id, from_template=template.id) }}" class="edit-template-link-letter-contact">Edit</a>
{% if default_letter_contact_block_id %}
<a href="{{ url_for(".service_edit_letter_contact", service_id=current_service.id, letter_contact_id=default_letter_contact_block_id, from_template=template.id) }}" class="edit-template-link-letter-contact">Edit</a>
{% else %}
<a href="{{ url_for(".service_add_letter_contact", service_id=current_service.id, from_template=template.id) }}" class="edit-template-link-letter-contact">Edit</a>
{% endif %}
{% endif %}
{{ template|string }}
</div>

View File

@@ -0,0 +1,141 @@
{% from "components/big-number.html" import big_number %}
{% from "components/table.html" import list_table, field, hidden_field_heading, row_heading, text_field %}
{% from "components/pill.html" import pill %}
{% extends "withnav_template.html" %}
{% block service_page_title %}
Usage
{% endblock %}
{% block maincolumn_content %}
<h1 class='heading-large'>Usage</h1>
<div class="bottom-gutter">
{{ pill(years, selected_year, big_number_args={'smallest': True}) }}
</div>
<div id='pill-selected-item'>
<div class='grid-row'>
<div class='column-one-third'>
<h2 class='heading-small'>Emails</h2>
<div class="keyline-block">
{{ big_number(emails_sent, 'sent', smaller=True) }}
{{ big_number("Unlimited", 'free allowance', smaller=True) }}
</div>
</div>
<div class='column-one-third'>
<h2 class='heading-small'>Text messages</h2>
<div class="keyline-block">
{{ big_number(sms_sent, 'sent', smaller=True) }}
{{ big_number(sms_free_allowance, 'free allowance', smaller=True) }}
{{ big_number(sms_allowance_remaining, 'free allowance remaining', smaller=True) }}
{% if sms_chargeable %}
{{ big_number(
sms_chargeable,
'at {:.2f} pence per message'.format(sms_rate * 100),
smaller=True
) }}
{% endif %}
</div>
</div>
<div class='column-one-third'>
<h2 class='heading-small'>Letters</h2>
<div class="keyline-block">
{{ big_number(letter_sent, 'sent', smaller=True) }}
</div>
</div>
</div>
<div class='grid-row'>
<div class='column-one-third'>
<div class="keyline-block">
&nbsp;
</div>
</div>
<div class='column-one-third'>
<div class="keyline-block">
{{ big_number(
(sms_chargeable * sms_rate),
'spent',
currency="£",
smaller=True
) }}
</div>
</div>
<div class='column-one-third'>
<div class="keyline-block">
{{ big_number(
letter_cost,
'spent',
currency="£",
smaller=True
) }}
</div>
</div>
</div>
{% if months %}
<div class="dashboard-table body-copy-table">
{% call(month, row_index) list_table(
months,
caption="Total spend",
caption_visible=False,
empty_message='',
field_headings=[
'By month',
hidden_field_heading('Cost'),
],
field_headings_visible=True
) %}
{% call row_heading() %}
{{ month.name }}
{% endcall %}
{% call field(align='left') %}
{{ big_number(
(sms_rate * month.paid) + month.letter_total,
currency="£",
smallest=True
) }}
<ul>
{% if month.free %}
<li class="tabular-numbers">{{ "{:,}".format(month.free) }} free text messages</li>
{% endif %}
{% if month.paid %}
<li class="tabular-numbers">{{ "{:,}".format(month.paid) }} text messages at
{{- ' {:.2f}p'.format(sms_rate * 100) }}</li>
{% endif %}
{% if not (month.free or month.paid) %}
<li aria-hidden="true"></li>
{% endif %}
</ul>
<ul>
{% for letter in month.letters%}
{% if letter[0] %}
<li class="tabular-numbers">{{ "{:,}".format(letter[0])}} letters at {{ '{:.0f}p'.format(letter[1] * 100) }}
</li>
{% endif %}
{% endfor %}
</ul>
{% endcall %}
{% endcall %}
</div>
{% endif %}
</div>
<div class="grid-row">
<div class="column-half">
<p class="align-with-heading-copy">
Financial year ends 31 March.
</p>
</div>
<div class="column-half">
<p class="align-with-heading-copy">
What counts as 1 text message?<br />
See <a href="{{ url_for('.pricing') }}">pricing</a>.
</p>
</div>
</div>
{% endblock %}

View File

@@ -113,4 +113,4 @@
</div>
</div>
{% endblock %}
{% endblock %}

View File

@@ -19,7 +19,7 @@
<p><a href="https://www.gov.uk/service-manual/design/sending-emails-and-text-messages">Check the Service Manual</a> for guidance on how to:</p>
<ul class="list list-bullet">
<li>plan and write text messages and emails</li>
<li><a href="https://www.gov.uk/service-manual/technology/how-to-email-your-users">send emails</a> in a way that protects users from spam and phishing</li>
<li>send emails in a way that protects users from spam and phishing</li>
</ul>
<h2 id="trial-mode" class="heading-medium">Trial mode</h2>