mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-18 05:30:21 -04:00
Add a redirect for the letter specification
This way we have a URL we can give people that always points to the latest version of the spec. And it makes our code more Flask-idiomatic to be using `url_for` to be generating a URL, rather than passing around a constant.
This commit is contained in:
@@ -17,11 +17,7 @@ from app.main import main
|
||||
from app.main.forms import FieldWithNoneOption, SearchByNameForm
|
||||
from app.main.views.feedback import QUESTION_TICKET_TYPE
|
||||
from app.main.views.sub_navigation_dictionaries import features_nav, pricing_nav
|
||||
from app.utils import (
|
||||
LETTER_SPECIFICATION_URL,
|
||||
get_logo_cdn_domain,
|
||||
user_is_logged_in,
|
||||
)
|
||||
from app.utils import get_logo_cdn_domain, user_is_logged_in
|
||||
|
||||
|
||||
@main.route('/')
|
||||
@@ -273,7 +269,6 @@ def features_sms():
|
||||
def features_letters():
|
||||
return render_template(
|
||||
'views/features/letters.html',
|
||||
letter_specification_url=LETTER_SPECIFICATION_URL,
|
||||
navigation_links=features_nav()
|
||||
)
|
||||
|
||||
@@ -348,3 +343,11 @@ def old_page_redirects():
|
||||
'main.old_integration_testing': 'main.integration_testing',
|
||||
}
|
||||
return redirect(url_for(redirects[request.endpoint]), code=301)
|
||||
|
||||
|
||||
@main.route('/docs/notify-pdf-letter-spec-latest.pdf')
|
||||
def letter_spec():
|
||||
return redirect(
|
||||
'https://docs.notifications.service.gov.uk'
|
||||
'/documentation/images/notify-pdf-letter-spec-v2.4.pdf'
|
||||
)
|
||||
|
||||
@@ -33,7 +33,6 @@ from app.s3_client.s3_letter_upload_client import (
|
||||
)
|
||||
from app.template_previews import TemplatePreview, sanitise_letter
|
||||
from app.utils import (
|
||||
LETTER_SPECIFICATION_URL,
|
||||
generate_next_dict,
|
||||
generate_previous_dict,
|
||||
get_letter_validation_error,
|
||||
@@ -66,7 +65,6 @@ def uploads(service_id):
|
||||
prev_page=prev_page,
|
||||
next_page=next_page,
|
||||
scheduled_jobs='',
|
||||
letter_specification_url=LETTER_SPECIFICATION_URL,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -208,6 +208,7 @@ class HeaderNavigation(Navigation):
|
||||
'invite_org_user',
|
||||
'invite_user',
|
||||
'no_cookie.letter_branding_preview_image',
|
||||
'letter_spec',
|
||||
'letter_template',
|
||||
'link_service_to_organisation',
|
||||
'manage_org_users',
|
||||
@@ -533,6 +534,7 @@ class MainNavigation(Navigation):
|
||||
'no_cookie.letter_branding_preview_image',
|
||||
'live_services',
|
||||
'live_services_csv',
|
||||
'letter_spec',
|
||||
'letter_template',
|
||||
'message_status',
|
||||
'manage_org_users',
|
||||
@@ -763,6 +765,7 @@ class CaseworkNavigation(Navigation):
|
||||
'invite_user',
|
||||
'no_cookie.letter_branding_preview_image',
|
||||
'letter_branding',
|
||||
'letter_spec',
|
||||
'letter_template',
|
||||
'link_service_to_organisation',
|
||||
'live_services',
|
||||
@@ -1049,6 +1052,7 @@ class OrgNavigation(Navigation):
|
||||
'invite_user',
|
||||
'letter_branding',
|
||||
'no_cookie.letter_branding_preview_image',
|
||||
'letter_spec',
|
||||
'letter_template',
|
||||
'link_service_to_organisation',
|
||||
'live_services',
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
<h3 class="heading heading-small" id="upload-letters">Upload your own letters</h3>
|
||||
<p>You can create reusable letter templates in Notify, or upload and send your own letters with the Notify API.</p>
|
||||
<p>Use the <a href="{{ letter_specification_url }}">letter specification document</a> to help you set up your letter, save it as a PDF, then upload it to Notify.<p>
|
||||
<p>Use the <a href="{{ url_for('.letter_spec') }}">letter specification document</a> to help you set up your letter, save it as a PDF, then upload it to Notify.<p>
|
||||
<p>Read our <a href="{{ url_for('.documentation') }}">API documentation</a> for more information.</p>
|
||||
|
||||
<h2 class="heading heading-medium">Pricing</h2>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
)}}
|
||||
</p>
|
||||
<p>You can upload a single letter as a PDF.</p>
|
||||
<p>Your file must meet our <a href="{{ letter_specification_url }}">letter specification</a>.</p>
|
||||
<p>Your file must meet our <a href="{{ url_for('.letter_spec') }}">letter specification</a>.</p>
|
||||
<p>To help you set up your letter you can download a <a href="https://docs.notifications.service.gov.uk/documentation/images/notify-pdf-letter-word-template-v1.0.docx">Word document template</a>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
20
app/utils.py
20
app/utils.py
@@ -566,33 +566,27 @@ def get_letter_printing_statement(status, created_at):
|
||||
return 'Printed on {} at 5:30pm'.format(printed_date)
|
||||
|
||||
|
||||
LETTER_SPECIFICATION_URL = (
|
||||
'https://docs.notifications.service.gov.uk'
|
||||
'/documentation/images/notify-pdf-letter-spec-v2.4.pdf'
|
||||
)
|
||||
|
||||
|
||||
LETTER_VALIDATION_MESSAGES = {
|
||||
'letter-not-a4-portrait-oriented': {
|
||||
'title': 'Your letter is not A4 portrait size',
|
||||
'detail': (
|
||||
'You need to change the size or orientation of {invalid_pages}. <br>'
|
||||
f'Files must meet our <a href="{LETTER_SPECIFICATION_URL}" target="_blank">letter specification</a>.'
|
||||
'Files must meet our <a href="{letter_spec}" target="_blank">letter specification</a>.'
|
||||
),
|
||||
'summary': (
|
||||
'Validation failed because {invalid_pages} {invalid_pages_are_or_is} not A4 portrait size.<br>'
|
||||
f'Files must meet our <a href="{LETTER_SPECIFICATION_URL}" target="_blank">letter specification</a>.'
|
||||
'Files must meet our <a href="{letter_spec}" target="_blank">letter specification</a>.'
|
||||
),
|
||||
},
|
||||
'content-outside-printable-area': {
|
||||
'title': 'Your content is outside the printable area',
|
||||
'detail': (
|
||||
'You need to edit {invalid_pages}.<br>'
|
||||
f'Files must meet our <a href="{LETTER_SPECIFICATION_URL}" target="_blank">letter specification</a>.'
|
||||
'Files must meet our <a href="{letter_spec}" target="_blank">letter specification</a>.'
|
||||
),
|
||||
'summary': (
|
||||
'Validation failed because content is outside the printable area on {invalid_pages}.<br>'
|
||||
f'Files must meet our <a href="{LETTER_SPECIFICATION_URL}" target="_blank">letter specification</a>.'
|
||||
'Files must meet our <a href="{letter_spec}" target="_blank">letter specification</a>.'
|
||||
),
|
||||
},
|
||||
'letter-too-long': {
|
||||
@@ -624,11 +618,11 @@ LETTER_VALIDATION_MESSAGES = {
|
||||
'title': 'The address block is empty',
|
||||
'detail': (
|
||||
'You need to add a recipient address.<br>'
|
||||
f'Files must meet our <a href="{LETTER_SPECIFICATION_URL}" target="_blank">letter specification</a>.'
|
||||
'Files must meet our <a href="{letter_spec}" target="_blank">letter specification</a>.'
|
||||
),
|
||||
'summary': (
|
||||
'Validation failed because the address block is empty.<br>'
|
||||
f'Files must meet our <a href="{LETTER_SPECIFICATION_URL}" target="_blank">letter specification</a>.'
|
||||
'Files must meet our <a href="{letter_spec}" target="_blank">letter specification</a>.'
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -654,11 +648,13 @@ def get_letter_validation_error(validation_message, invalid_pages=None, page_cou
|
||||
invalid_pages=invalid_pages,
|
||||
invalid_pages_are_or_is=invalid_pages_are_or_is,
|
||||
page_count=page_count,
|
||||
letter_spec=url_for('.letter_spec'),
|
||||
),
|
||||
'summary': LETTER_VALIDATION_MESSAGES[validation_message]['summary'].format(
|
||||
invalid_pages=invalid_pages,
|
||||
invalid_pages_are_or_is=invalid_pages_are_or_is,
|
||||
page_count=page_count,
|
||||
letter_spec=url_for('.letter_spec'),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -254,3 +254,21 @@ def test_letter_template_preview_headers(
|
||||
)
|
||||
|
||||
assert response.headers.get('X-Frame-Options') == 'SAMEORIGIN'
|
||||
|
||||
|
||||
def test_letter_spec_redirect(client_request):
|
||||
expected_url = (
|
||||
'https://docs.notifications.service.gov.uk'
|
||||
'/documentation/images/notify-pdf-letter-spec-v2.4.pdf'
|
||||
)
|
||||
client_request.get(
|
||||
'main.letter_spec',
|
||||
_expected_status=302,
|
||||
_expected_redirect=expected_url,
|
||||
)
|
||||
client_request.logout()
|
||||
client_request.get(
|
||||
'main.letter_spec',
|
||||
_expected_status=302,
|
||||
_expected_redirect=expected_url,
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app import format_datetime_relative
|
||||
@@ -454,15 +455,12 @@ def test_get_letter_validation_error_for_unknown_error():
|
||||
),
|
||||
])
|
||||
def test_get_letter_validation_error_for_known_errors(
|
||||
client_request,
|
||||
error_message,
|
||||
expected_title,
|
||||
expected_content,
|
||||
expected_summary,
|
||||
):
|
||||
expected_letter_spec_url = (
|
||||
'https://docs.notifications.service.gov.uk/'
|
||||
'documentation/images/notify-pdf-letter-spec-v2.4.pdf'
|
||||
)
|
||||
error = get_letter_validation_error(error_message, invalid_pages=[2], page_count=13)
|
||||
detail = BeautifulSoup(error['detail'], 'html.parser')
|
||||
summary = BeautifulSoup(error['summary'], 'html.parser')
|
||||
@@ -471,10 +469,10 @@ def test_get_letter_validation_error_for_known_errors(
|
||||
|
||||
assert detail.text == expected_content
|
||||
if detail.select_one('a'):
|
||||
assert detail.select_one('a')['href'] == expected_letter_spec_url
|
||||
assert detail.select_one('a')['href'] == url_for('.letter_spec')
|
||||
assert detail.select_one('a')['target'] == '_blank'
|
||||
|
||||
assert summary.text == expected_summary
|
||||
if summary.select_one('a'):
|
||||
assert summary.select_one('a')['href'] == expected_letter_spec_url
|
||||
assert summary.select_one('a')['href'] == url_for('.letter_spec')
|
||||
assert summary.select_one('a')['target'] == '_blank'
|
||||
|
||||
Reference in New Issue
Block a user