mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-11 10:28:41 -04:00
Merge pull request #781 from alphagov/template-previews
Adds previews of email templates
This commit is contained in:
+7
-2
@@ -303,8 +303,13 @@ def useful_headers_after_request(response):
|
|||||||
response.headers.add('X-Frame-Options', 'deny')
|
response.headers.add('X-Frame-Options', 'deny')
|
||||||
response.headers.add('X-Content-Type-Options', 'nosniff')
|
response.headers.add('X-Content-Type-Options', 'nosniff')
|
||||||
response.headers.add('X-XSS-Protection', '1; mode=block')
|
response.headers.add('X-XSS-Protection', '1; mode=block')
|
||||||
response.headers.add('Content-Security-Policy',
|
response.headers.add('Content-Security-Policy', (
|
||||||
"default-src 'self' 'unsafe-inline'; script-src 'self' *.google-analytics.com 'unsafe-inline' data:; object-src 'self'; font-src 'self' data:; img-src 'self' *.google-analytics.com data:;") # noqa
|
"default-src 'self' 'unsafe-inline';"
|
||||||
|
"script-src 'self' *.google-analytics.com 'unsafe-inline' data:;"
|
||||||
|
"object-src 'self';"
|
||||||
|
"font-src 'self' data:;"
|
||||||
|
"img-src 'self' *.google-analytics.com *.notifications.service.gov.uk data:;"
|
||||||
|
))
|
||||||
if 'Cache-Control' in response.headers:
|
if 'Cache-Control' in response.headers:
|
||||||
del response.headers['Cache-Control']
|
del response.headers['Cache-Control']
|
||||||
response.headers.add(
|
response.headers.add(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
!('oninput' in document.createElement('input'))
|
!('oninput' in document.createElement('input'))
|
||||||
) return;
|
) return;
|
||||||
|
|
||||||
const tagPattern = /\(\([^\)\(]+\)\)/g;
|
const tagPattern = /\(\(([^\)\((\?)]+)(\?\?)?([^\)\(]*)\)\)/g;
|
||||||
|
|
||||||
Modules.HighlightTags = function() {
|
Modules.HighlightTags = function() {
|
||||||
|
|
||||||
@@ -43,7 +43,9 @@
|
|||||||
|
|
||||||
this.replacePlaceholders = () => this.$background.html(
|
this.replacePlaceholders = () => this.$background.html(
|
||||||
this.escapedMessage().replace(
|
this.escapedMessage().replace(
|
||||||
tagPattern, match => `<span class='placeholder'>${match}</span>`
|
tagPattern, (match, name, separator, value) => value && separator ?
|
||||||
|
`<span class='placeholder-conditional'>((${name}??</span>${value}))` :
|
||||||
|
`<span class='placeholder'>((${name}${value}))</span>`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,19 @@
|
|||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
box-shadow: inset 0 -2px 0 0 $white, inset 0 2px 0 0 $white;
|
box-shadow: inset 0 -2px 0 0 $white, inset 0 2px 0 0 $white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.placeholder-conditional {
|
||||||
|
|
||||||
|
@extend %placeholder;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top-left-radius: 20px;
|
||||||
|
border-bottom-left-radius: 20px;
|
||||||
|
border-top-right-radius: 8px;
|
||||||
|
border-bottom-right-radius: 8px;
|
||||||
|
box-shadow: inset 9px 0 0 0 $white, inset -17px 0 0 0 $white, inset 0 -3px 0 0 $white, inset 0 3px 0 0 $white;
|
||||||
|
|
||||||
|
.sms-message-wrapper & {
|
||||||
|
box-shadow: inset 9px 0 0 0 $panel-colour, inset -17px 0 0 0 $panel-colour, inset 0 -3.5px 0 0 $panel-colour, inset 0 3.5px 0 0 $panel-colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+40
-1
@@ -1,12 +1,15 @@
|
|||||||
import markdown
|
import markdown
|
||||||
import os
|
import os
|
||||||
from flask import (render_template, url_for, redirect, Markup)
|
from flask import (render_template, url_for, redirect, Markup, request)
|
||||||
from app.main import main
|
from app.main import main
|
||||||
|
from app import convert_to_boolean
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from flask.ext.login import current_user
|
from flask.ext.login import current_user
|
||||||
from mdx_gfm import GithubFlavoredMarkdownExtension
|
from mdx_gfm import GithubFlavoredMarkdownExtension
|
||||||
|
|
||||||
|
from notifications_utils.renderers import HTMLEmail
|
||||||
|
|
||||||
|
|
||||||
@main.route('/')
|
@main.route('/')
|
||||||
def index():
|
def index():
|
||||||
@@ -46,6 +49,42 @@ def delivery_and_failure():
|
|||||||
return render_template('views/delivery-and-failure.html')
|
return render_template('views/delivery-and-failure.html')
|
||||||
|
|
||||||
|
|
||||||
|
@main.route('/_email')
|
||||||
|
def email_template():
|
||||||
|
return HTMLEmail(
|
||||||
|
govuk_banner=convert_to_boolean(request.args.get('govuk_banner', True))
|
||||||
|
)(
|
||||||
|
'Lorem Ipsum is simply dummy text of the printing and typesetting '
|
||||||
|
'industry.\n\nLorem Ipsum has been the industry’s standard dummy '
|
||||||
|
'text ever since the 1500s, when an unknown printer took a galley '
|
||||||
|
'of type and scrambled it to make a type specimen book. '
|
||||||
|
'\n\n'
|
||||||
|
'# History'
|
||||||
|
'\n\n'
|
||||||
|
'It has '
|
||||||
|
'survived not only'
|
||||||
|
'\n'
|
||||||
|
'*five centuries'
|
||||||
|
'\n'
|
||||||
|
'* but also the leap into electronic typesetting'
|
||||||
|
'\n\n'
|
||||||
|
'It was '
|
||||||
|
'popularised in the 1960s with the release of Letraset sheets '
|
||||||
|
'containing Lorem Ipsum passages, and more recently with desktop '
|
||||||
|
'publishing software like Aldus PageMaker including versions of '
|
||||||
|
'Lorem Ipsum.'
|
||||||
|
'\n\n'
|
||||||
|
'^ It is a long established fact that a reader will be distracted '
|
||||||
|
'by the readable content of a page when looking at its layout.'
|
||||||
|
'\n\n'
|
||||||
|
'The point of using Lorem Ipsum is that it has a more-or-less '
|
||||||
|
'normal distribution of letters, as opposed to using ‘Content '
|
||||||
|
'here, content here’, making it look like readable English.'
|
||||||
|
'\n\n\n'
|
||||||
|
'This is an example of an email sent using GOV.UK Notify.'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@main.route('/documentation')
|
@main.route('/documentation')
|
||||||
def documentation():
|
def documentation():
|
||||||
curr_dir = os.path.dirname(os.path.realpath(__file__))
|
curr_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
recipient=None,
|
recipient=None,
|
||||||
id=None,
|
id=None,
|
||||||
show_placeholder_for_recipient=False,
|
show_placeholder_for_recipient=False,
|
||||||
show_id=False
|
show_id=False,
|
||||||
|
expanded=False
|
||||||
) %}
|
) %}
|
||||||
<div class="email-message">
|
<div class="email-message">
|
||||||
{% if from_name or subject %}
|
{% if from_name or subject %}
|
||||||
@@ -45,11 +46,15 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="email-message-body" data-module="expand-collapse" data-max-height="200">
|
<div class="email-message-body" {% if not expanded %}data-module="expand-collapse" data-max-height="200"{% endif %}>
|
||||||
|
{% if not expanded %}
|
||||||
<div class="email-message-body-wrapper">
|
<div class="email-message-body-wrapper">
|
||||||
{{ body|nl2br }}
|
{% endif %}
|
||||||
|
{{ body|nl2br }}
|
||||||
|
{% if not expanded %}
|
||||||
</div>
|
</div>
|
||||||
<div class='toggle' tabindex='0'>...<span class='visually-hidden'>show full email</span></div>
|
<div class='toggle' tabindex='0'>...<span class='visually-hidden'>show full email</span></div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@
|
|||||||
{% if 'email' == template.template_type %}
|
{% if 'email' == template.template_type %}
|
||||||
{{ email_message(
|
{{ email_message(
|
||||||
template.formatted_subject_as_markup if errors else template.replaced_subject,
|
template.formatted_subject_as_markup if errors else template.replaced_subject,
|
||||||
template.formatted_as_markup if errors else template.replaced,
|
template.formatted_as_markup if errors else template.replaced|safe,
|
||||||
from_address='{}@notifications.service.gov.uk'.format(current_service.email_from),
|
from_address='{}@notifications.service.gov.uk'.format(current_service.email_from),
|
||||||
from_name=current_service.name,
|
from_name=current_service.name,
|
||||||
recipient=first_recipient,
|
recipient=first_recipient,
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="column-two-thirds">
|
<div class="column-two-thirds">
|
||||||
{{ sms_message(
|
{{ sms_message(
|
||||||
template.formatted_as_markup if errors else template.replaced,
|
template.formatted_as_markup if errors else template.replaced|safe,
|
||||||
recipient=first_recipient,
|
recipient=first_recipient,
|
||||||
show_placeholder_for_recipient=errors
|
show_placeholder_for_recipient=errors
|
||||||
)}}
|
)}}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
{{ email_message(
|
{{ email_message(
|
||||||
template.formatted_subject_as_markup,
|
template.formatted_subject_as_markup,
|
||||||
template.formatted_as_markup,
|
template.formatted_as_markup,
|
||||||
id=template.id
|
id=template.id,
|
||||||
|
expanded=expanded
|
||||||
) }}
|
) }}
|
||||||
{% elif 'sms' == template.template_type %}
|
{% elif 'sms' == template.template_type %}
|
||||||
{{ sms_message(
|
{{ sms_message(
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<h1 class="heading-large">{{ template.name }}</h1>
|
<h1 class="heading-large">{{ template.name }}</h1>
|
||||||
|
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
{% with show_title=False %}
|
{% with show_title=False, expanded=True %}
|
||||||
{% include 'views/templates/_template.html' %}
|
{% include 'views/templates/_template.html' %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -18,4 +18,4 @@ pytz==2016.4
|
|||||||
|
|
||||||
git+https://github.com/alphagov/notifications-python-client.git@1.0.0#egg=notifications-python-client==1.0.0
|
git+https://github.com/alphagov/notifications-python-client.git@1.0.0#egg=notifications-python-client==1.0.0
|
||||||
|
|
||||||
git+https://github.com/alphagov/notifications-utils.git@6.2.0#egg=notifications-utils==6.2.0
|
git+https://github.com/alphagov/notifications-utils.git@8.4.1#egg=notifications-utils==8.4.1
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import pytest
|
||||||
|
from flask import url_for
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"query_args, params", [
|
||||||
|
({}, {'govuk_banner': True}),
|
||||||
|
({'govuk_banner': 'false'}, {'govuk_banner': False})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_renders(app_, mocker, query_args, params):
|
||||||
|
with app_.test_request_context(), app_.test_client() as client:
|
||||||
|
|
||||||
|
mock_html_email = mocker.patch(
|
||||||
|
'app.main.views.index.HTMLEmail',
|
||||||
|
return_value=lambda x: 'rendered'
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.get(url_for('main.email_template', **query_args))
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.get_data(as_text=True) == 'rendered'
|
||||||
|
mock_html_email.assert_called_once_with(**params)
|
||||||
@@ -6,4 +6,10 @@ def test_owasp_useful_headers_set(app_):
|
|||||||
assert response.headers['X-Frame-Options'] == 'deny'
|
assert response.headers['X-Frame-Options'] == 'deny'
|
||||||
assert response.headers['X-Content-Type-Options'] == 'nosniff'
|
assert response.headers['X-Content-Type-Options'] == 'nosniff'
|
||||||
assert response.headers['X-XSS-Protection'] == '1; mode=block'
|
assert response.headers['X-XSS-Protection'] == '1; mode=block'
|
||||||
assert response.headers['Content-Security-Policy'] == "default-src 'self' 'unsafe-inline'; script-src 'self' *.google-analytics.com 'unsafe-inline' data:; object-src 'self'; font-src 'self' data:; img-src 'self' *.google-analytics.com data:;" # noqa
|
assert response.headers['Content-Security-Policy'] == (
|
||||||
|
"default-src 'self' 'unsafe-inline';"
|
||||||
|
"script-src 'self' *.google-analytics.com 'unsafe-inline' data:;"
|
||||||
|
"object-src 'self';"
|
||||||
|
"font-src 'self' data:;"
|
||||||
|
"img-src 'self' *.google-analytics.com *.notifications.service.gov.uk data:;"
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user