Show letter preview once file is uploaded

This shows the sanitised letter preview if the file had no validation
errors or the preview with the overlay if it failed validation.
This commit is contained in:
Katie Smith
2019-09-09 10:59:32 +01:00
parent 8a322b844b
commit 7368245c9a
9 changed files with 228 additions and 6 deletions

View File

@@ -13,16 +13,17 @@ from notifications_utils.pdf import pdf_page_count
from PyPDF2.utils import PdfReadError
from requests import RequestException
from app import current_service
from app import current_service, service_api_client
from app.extensions import antivirus_client
from app.main import main
from app.main.forms import PDFUploadForm
from app.s3_client.s3_letter_upload_client import (
get_letter_pdf_and_metadata,
get_transient_letter_file_location,
upload_letter_to_s3,
)
from app.template_previews import sanitise_letter
from app.utils import user_has_permissions
from app.template_previews import TemplatePreview, sanitise_letter
from app.utils import get_template, user_has_permissions
MAX_FILE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB
@@ -49,7 +50,7 @@ def upload_letter(service_id):
return invalid_upload_error('Your file must be smaller than 2MB')
try:
pdf_page_count(BytesIO(pdf_file_bytes))
page_count = pdf_page_count(BytesIO(pdf_file_bytes))
except PdfReadError:
current_app.logger.info('Invalid PDF uploaded for service_id: {}'.format(service_id))
return invalid_upload_error('Your file must be a valid PDF')
@@ -76,6 +77,7 @@ def upload_letter(service_id):
service_id=current_service.id,
file_id=upload_id,
original_filename=form.file.data.filename,
page_count=page_count,
status=status,
)
)
@@ -92,6 +94,39 @@ def invalid_upload_error(message):
@user_has_permissions('send_messages')
def uploaded_letter_preview(service_id, file_id):
original_filename = request.args.get('original_filename')
page_count = request.args.get('page_count')
status = request.args.get('status')
return render_template('views/uploads/preview.html', original_filename=original_filename, status=status)
template_dict = service_api_client.get_precompiled_template(service_id)
template = get_template(
template_dict,
service_id,
letter_preview_url=url_for(
'.view_letter_upload_as_preview',
service_id=service_id,
file_id=file_id
),
page_count=page_count
)
return render_template(
'views/uploads/preview.html',
original_filename=original_filename,
template=template,
status=status,
)
@main.route("/services/<service_id>/preview-letter-image/<file_id>")
@user_has_permissions('send_messages')
def view_letter_upload_as_preview(service_id, file_id):
file_location = get_transient_letter_file_location(service_id, file_id)
pdf_file, metadata = get_letter_pdf_and_metadata(file_location)
page = request.args.get('page')
if metadata['status'] == 'invalid':
return TemplatePreview.from_invalid_pdf_file(pdf_file, page)
else:
return TemplatePreview.from_valid_pdf_file(pdf_file, page)

View File

@@ -314,6 +314,7 @@ class HeaderNavigation(Navigation):
'view_jobs',
'view_letter_notification_as_preview',
'view_letter_template_preview',
'view_letter_upload_as_preview',
'view_notification',
'view_notification_updates',
'view_notifications',
@@ -607,6 +608,7 @@ class MainNavigation(Navigation):
'view_job_updates',
'view_letter_notification_as_preview',
'view_letter_template_preview',
'view_letter_upload_as_preview',
'view_notification_updates',
'view_notifications_csv',
'view_provider',
@@ -887,6 +889,7 @@ class CaseworkNavigation(Navigation):
'view_job_updates',
'view_letter_notification_as_preview',
'view_letter_template_preview',
'view_letter_upload_as_preview',
'view_notification_updates',
'view_notifications_csv',
'view_provider',
@@ -1170,6 +1173,7 @@ class OrgNavigation(Navigation):
'view_jobs',
'view_letter_notification_as_preview',
'view_letter_template_preview',
'view_letter_upload_as_preview',
'view_notification',
'view_notification_updates',
'view_notifications',

View File

@@ -261,6 +261,12 @@ class ServiceAPIClient(NotifyAdminAPIClient):
)
return self.get(endpoint)
def get_precompiled_template(self, service_id):
"""
Returns the precompiled template for a service, creating it if it doesn't already exist
"""
return self.get('/service/{}/template/precompiled'.format(service_id))
@cache.set('service-{service_id}-templates')
def get_service_templates(self, service_id):
"""

View File

@@ -1,3 +1,4 @@
from boto3 import resource
from flask import current_app
from notifications_utils.s3 import s3upload as utils_s3upload
@@ -14,3 +15,13 @@ def upload_letter_to_s3(data, file_location, status):
file_location=file_location,
metadata={'status': status}
)
def get_letter_pdf_and_metadata(file_location):
s3 = resource('s3')
s3_object = s3.Object(current_app.config['TRANSIENT_UPLOADED_LETTERS'], file_location).get()
pdf = s3_object['Body'].read()
metadata = s3_object['Metadata']
return pdf, metadata

View File

@@ -1,5 +1,9 @@
import base64
from io import BytesIO
import requests
from flask import current_app, json
from notifications_utils.pdf import extract_page_from_pdf
from app import current_service
@@ -24,6 +28,36 @@ class TemplatePreview:
)
return (resp.content, resp.status_code, resp.headers.items())
@classmethod
def from_valid_pdf_file(cls, pdf_file, page):
pdf_page = extract_page_from_pdf(BytesIO(pdf_file), int(page) - 1)
response = requests.post(
'{}/precompiled-preview.png{}'.format(
current_app.config['TEMPLATE_PREVIEW_API_HOST'],
'?hide_notify=true' if page == '1' else ''
),
data=base64.b64encode(pdf_page).decode('utf-8'),
headers={'Authorization': 'Token {}'.format(current_app.config['TEMPLATE_PREVIEW_API_KEY'])}
)
return (response.content, response.status_code, response.headers.items())
@classmethod
def from_invalid_pdf_file(cls, pdf_file, page):
pdf_page = extract_page_from_pdf(BytesIO(pdf_file), int(page) - 1)
response = requests.post(
'{}/precompiled/overlay.png{}'.format(
current_app.config['TEMPLATE_PREVIEW_API_HOST'],
'?page_number={}'.format(page)
),
data=pdf_page,
headers={'Authorization': 'Token {}'.format(current_app.config['TEMPLATE_PREVIEW_API_KEY'])}
)
return (response.content, response.status_code, response.headers.items())
@classmethod
def from_example_template(cls, template, filename):
data = {

View File

@@ -16,4 +16,8 @@
Validation failed
</p>
{% endif %}
<div class="letter-sent">
{{ template|string }}
</div>
{% endblock %}