Refactor to move preview logic to API

* Moved the notifications code to go to admin to get the the template

preview document rather than go to template preview.

This will remove the logic from admin and place it in api so it is
easier to expand on later when there are precompiled PDFs

* Added some error handling if API returns an API error.

Caught the error and displayed an error PNG so it is obvious something
failed. Currently it displayed a thumbnail of a png over the top of the
loading page, and therefore it wasn't obvious of the state.
This commit is contained in:
Ken Tsang
2018-03-08 12:25:07 +00:00
parent 61b8c9040a
commit 4628b99445
4 changed files with 66 additions and 22 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
import base64
import os
from datetime import datetime
from flask import (
@@ -11,6 +13,7 @@ from flask import (
url_for,
)
from flask_login import login_required
from notifications_python_client.errors import APIError
from app import (
current_service,
@@ -19,7 +22,7 @@ from app import (
notification_api_client,
)
from app.main import main
from app.template_previews import TemplatePreview, get_page_count_for_letter
from app.template_previews import get_page_count_for_letter
from app.utils import (
DELIVERED_STATUSES,
FAILURE_STATUSES,
@@ -83,6 +86,12 @@ def view_notification(service_id, notification_id):
)
def get_preview_error_image():
path = os.path.join(os.path.dirname(__file__), "..", "..", "assets", "images", "preview_error.png")
with open(path, "rb") as file:
return file.read()
@main.route("/services/<service_id>/notification/<uuid:notification_id>.<filetype>")
@login_required
@user_has_permissions('view_activity')
@@ -91,23 +100,19 @@ def view_letter_notification_as_preview(service_id, notification_id, filetype):
if filetype not in ('pdf', 'png'):
abort(404)
notification = notification_api_client.get_notification(service_id, notification_id)
notification['template'].update({'reply_to_text': notification['reply_to_text']})
try:
preview = notification_api_client.get_notification_letter_preview(
service_id,
notification_id,
filetype,
page=request.args.get('page')
)
template = get_template(
notification['template'],
current_service,
letter_preview_url=url_for(
'.view_letter_notification_as_preview',
service_id=service_id,
notification_id=notification_id,
filetype='png',
),
)
display_file = base64.b64decode(preview['content'])
except APIError:
display_file = get_preview_error_image()
template.values = notification['personalisation']
return TemplatePreview.from_utils_template(template, filetype, page=request.args.get('page'))
return display_file
@main.route("/services/<service_id>/notification/<notification_id>.json")

View File

@@ -73,3 +73,14 @@ class NotificationApiClient(NotifyAdminAPIClient):
if notification['notification_type'] == 'letter' and notification['status'] in ('created', 'sending'):
notification['status'] = 'accepted'
return notifications
def get_notification_letter_preview(self, service_id, notification_id, file_type, page=None):
get_url = '/service/{}/template/preview/{}/{}{}'.format(
service_id,
notification_id,
file_type,
'?page={}'.format(page) if page else ''
)
return self.get(url=get_url)

View File

@@ -1,9 +1,11 @@
import base64
from functools import partial
from unittest.mock import mock_open
import pytest
from flask import url_for
from freezegun import freeze_time
from notifications_utils.template import LetterImageTemplate
from notifications_python_client.errors import APIError
from tests.conftest import (
SERVICE_ONE_ID,
mock_get_notification,
@@ -163,9 +165,11 @@ def test_should_show_image_of_letter_notification(
mock_get_notification(mocker, fake_uuid, template_type='letter')
mocked_preview = mocker.patch(
'app.main.views.templates.TemplatePreview.from_utils_template',
return_value='foo'
mocker.patch(
'app.notify_client.notification_api_client.NotificationApiClient.get',
return_value={
'content': base64.b64encode(b'foo').decode('utf-8')
}
)
response = logged_in_client.get(url_for(
@@ -177,8 +181,32 @@ def test_should_show_image_of_letter_notification(
assert response.status_code == 200
assert response.get_data(as_text=True) == 'foo'
assert isinstance(mocked_preview.call_args[0][0], LetterImageTemplate)
assert mocked_preview.call_args[0][1] == filetype
def test_should_show_preview_error_image_letter_notification_on_preview_error(
logged_in_client,
fake_uuid,
mocker,
):
mock_get_notification(mocker, fake_uuid, template_type='letter')
mocker.patch(
'app.notify_client.notification_api_client.NotificationApiClient.get',
side_effect=APIError
)
mocker.patch("builtins.open", mock_open(read_data="preview error image"))
response = logged_in_client.get(url_for(
'main.view_letter_notification_as_preview',
service_id=SERVICE_ONE_ID,
notification_id=fake_uuid,
filetype='png'
))
assert response.status_code == 200
assert response.get_data(as_text=True) == 'preview error image'
def test_should_404_for_unknown_extension(