mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-06 08:18:24 -04:00
Merge pull request #1195 from alphagov/better-template-management
Make it easier to find and preview templates
This commit is contained in:
44
app/assets/javascripts/liveSearch.js
Normal file
44
app/assets/javascripts/liveSearch.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
(function(Modules) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let normalize = (string) => string.toLowerCase().replace(/ /g,'');
|
||||||
|
|
||||||
|
let filter = ($searchBox, $targets) => () => {
|
||||||
|
|
||||||
|
let query = normalize($searchBox.val());
|
||||||
|
|
||||||
|
$targets.each(function() {
|
||||||
|
|
||||||
|
let content = $(this).text();
|
||||||
|
|
||||||
|
$(this).toggle(
|
||||||
|
normalize(content).indexOf(normalize(query)) > -1
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Modules.LiveSearch = function() {
|
||||||
|
|
||||||
|
this.start = function(component) {
|
||||||
|
|
||||||
|
let $component = $(component);
|
||||||
|
|
||||||
|
let $searchBox = $('input', $component);
|
||||||
|
|
||||||
|
let filterFunc = filter(
|
||||||
|
$searchBox,
|
||||||
|
$($component.data('targets'))
|
||||||
|
);
|
||||||
|
|
||||||
|
$searchBox.on('keyup input', filterFunc);
|
||||||
|
|
||||||
|
filterFunc();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
})(window.GOVUK.Modules);
|
||||||
@@ -39,6 +39,11 @@
|
|||||||
margin-bottom: $gutter-half;
|
margin-bottom: $gutter-half;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bottom-gutter-1-3 {
|
||||||
|
@extend %bottom-gutter;
|
||||||
|
margin-bottom: $gutter/3;
|
||||||
|
}
|
||||||
|
|
||||||
.bottom-gutter-3-2 {
|
.bottom-gutter-3-2 {
|
||||||
@extend %bottom-gutter;
|
@extend %bottom-gutter;
|
||||||
margin-bottom: $gutter * 3/2;
|
margin-bottom: $gutter * 3/2;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
$white-50-opaque: rgba($white, 0.5);
|
$white-50-opaque: rgba($white, 0.5);
|
||||||
$button-bottom-border-colour: rgba(0, 0, 0, 0.17);
|
$button-bottom-border-colour: rgba(0, 0, 0, 0.17);
|
||||||
|
$email-message-gutter: $gutter * 2;
|
||||||
|
|
||||||
.email-message {
|
.email-message {
|
||||||
|
|
||||||
margin-bottom: $gutter;
|
margin-bottom: $gutter;
|
||||||
|
border: 1px solid $border-colour;
|
||||||
|
|
||||||
&-meta {
|
&-meta {
|
||||||
|
|
||||||
@@ -13,35 +15,34 @@ $button-bottom-border-colour: rgba(0, 0, 0, 0.17);
|
|||||||
td,
|
td,
|
||||||
th {
|
th {
|
||||||
@include core-19;
|
@include core-19;
|
||||||
border-bottom: 0;
|
border-top: 0;
|
||||||
border-top: 1px solid $border-colour;
|
border-bottom: 1px solid $border-colour;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
color: $secondary-text-colour;
|
color: $secondary-text-colour;
|
||||||
|
padding-left: $email-message-gutter;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
width: 99%;
|
width: 99%;
|
||||||
|
padding-right: $email-message-gutter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-from {
|
&-from {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
border-top: 1px solid $border-colour;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-body {
|
&-body {
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: $gutter-half 0 0 0;
|
padding: $gutter-half $email-message-gutter 0 $email-message-gutter;
|
||||||
margin: 0 0 $gutter * 1.5 0;
|
margin: 0 0 0 0;
|
||||||
clear: both;
|
clear: both;
|
||||||
border-top: 1px solid $border-colour;
|
|
||||||
border-bottom: 1px solid $border-colour;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
@@ -49,11 +50,13 @@ $button-bottom-border-colour: rgba(0, 0, 0, 0.17);
|
|||||||
|
|
||||||
.js-enabled & {
|
.js-enabled & {
|
||||||
max-height: 92px;
|
max-height: 92px;
|
||||||
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.js-enabled .expanded & {
|
.js-enabled .expanded & {
|
||||||
max-height: none;
|
max-height: none;
|
||||||
|
padding-bottom: $gutter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,34 @@
|
|||||||
// Easing function from: http://easings.net/#easeOutBack
|
$iso-paper-ratio: 141.42135624%;
|
||||||
$transition-easing: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
||||||
$iso-paper-ratio: 70.710678118%;
|
@keyframes ellipsis {
|
||||||
|
to {
|
||||||
|
width: 1.25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.letter {
|
.letter {
|
||||||
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0 0 $gutter 0;
|
margin: 0 0 $gutter 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background: $panel-colour;
|
||||||
&:after {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
z-index: 10;
|
|
||||||
position: absolute;
|
|
||||||
top: 1px;
|
|
||||||
left: 5px;
|
|
||||||
height: 0;
|
|
||||||
padding: $iso-paper-ratio 0 0 0;
|
|
||||||
width: 100%;
|
|
||||||
background: $highlight-colour;
|
|
||||||
transform-origin: left bottom;
|
|
||||||
transform: scale(1, 0.985);
|
|
||||||
box-shadow: inset 0 0 0 1px $border-colour;
|
|
||||||
transition: all 0.2s $transition-easing;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
|
||||||
z-index: 15;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -3px;
|
top: 10%;
|
||||||
right: -5px;
|
left: 50%;
|
||||||
width: 4px;
|
margin-left: -0.5em;
|
||||||
height: 7px;
|
font-size: 96px;
|
||||||
background: $white;
|
color: $white;
|
||||||
transform: rotate(45deg);
|
overflow: hidden;
|
||||||
box-shadow: inset 1px 0 0 0 $border-colour;
|
display: block;
|
||||||
}
|
vertical-align: bottom;
|
||||||
|
animation: ellipsis steps(4,end) 1.3s infinite;
|
||||||
&:hover {
|
content: "\2026"; // ellipsis
|
||||||
|
width: 0px;
|
||||||
&:after {
|
|
||||||
transform: skew(-1.3deg, 0deg) scale(1, 0.96);
|
|
||||||
transition: all 0.1s $transition-easing;
|
|
||||||
background: mix($highlight-colour, $white);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
transform: rotate(50deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -61,19 +36,6 @@ $iso-paper-ratio: 70.710678118%;
|
|||||||
padding: $iso-paper-ratio 0 0 0;
|
padding: $iso-paper-ratio 0 0 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
box-shadow: 0 1px 0 0 $border-colour;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
|
|
||||||
outline: none;
|
|
||||||
box-shadow: 0 3px 0 0 $yellow;
|
|
||||||
|
|
||||||
img {
|
|
||||||
box-shadow: inset 0 0 0 3px $yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
|||||||
16
app/assets/stylesheets/components/live-search.scss
Normal file
16
app/assets/stylesheets/components/live-search.scss
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
input[type=search] {
|
||||||
|
// overrides this nasty global from GOV.UK template
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.live-search {
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.js-enabled & {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
.sms-message-wrapper {
|
.sms-message-wrapper {
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 410px;
|
max-width: 450px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: $gutter-half;
|
padding: $gutter-half $gutter-half $gutter-half $gutter-half;
|
||||||
background: $panel-colour;
|
background: $panel-colour;
|
||||||
border: 1px solid $panel-colour;
|
border: 1px solid $panel-colour;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
%tick-cross {
|
%tick-cross {
|
||||||
|
|
||||||
@include core-16;
|
@include core-19;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-size: 19px 19px;
|
background-size: 19px 19px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ $path: '/static/images/';
|
|||||||
@import 'components/tick-cross';
|
@import 'components/tick-cross';
|
||||||
@import 'components/list-entry';
|
@import 'components/list-entry';
|
||||||
@import 'components/letter';
|
@import 'components/letter';
|
||||||
|
@import 'components/live-search';
|
||||||
@import 'components/vendor/breadcrumbs';
|
@import 'components/vendor/breadcrumbs';
|
||||||
@import 'components/vendor/responsive-embed';
|
@import 'components/vendor/responsive-embed';
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ $path: '/static/images/';
|
|||||||
@import 'views/users';
|
@import 'views/users';
|
||||||
@import 'views/api';
|
@import 'views/api';
|
||||||
@import 'views/product-page';
|
@import 'views/product-page';
|
||||||
|
@import 'views/template';
|
||||||
|
|
||||||
// TODO: break this up
|
// TODO: break this up
|
||||||
@import 'app';
|
@import 'app';
|
||||||
|
|||||||
41
app/assets/stylesheets/views/template.scss
Normal file
41
app/assets/stylesheets/views/template.scss
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
.template-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
%edit-template-link,
|
||||||
|
.edit-template-link {
|
||||||
|
|
||||||
|
@include core-19;
|
||||||
|
position: absolute;
|
||||||
|
background: $link-colour;
|
||||||
|
color: $white;
|
||||||
|
padding: 10px $gutter-half;
|
||||||
|
z-index: 10000;
|
||||||
|
|
||||||
|
&:link, &:visited {
|
||||||
|
color: $white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $light-blue-25;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-template-link-letter-contact {
|
||||||
|
@extend %edit-template-link;
|
||||||
|
right: -25px;
|
||||||
|
top: 13.3%; // align to top of contact block
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-template-link-letter-address {
|
||||||
|
@extend %edit-template-link;
|
||||||
|
top: 16.5%; // align bottom edge to bottom of address
|
||||||
|
left: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-template-link-letter-body {
|
||||||
|
@extend %edit-template-link;
|
||||||
|
top: 33.3%; // aligns to top of subject
|
||||||
|
left: -5px;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
.user-list {
|
.user-list {
|
||||||
|
|
||||||
@include core-16;
|
@include core-19;
|
||||||
margin-bottom: $gutter * 1.5;
|
margin-bottom: $gutter * 1.5;
|
||||||
|
|
||||||
&-item {
|
&-item {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from wtforms import (
|
|||||||
FieldList,
|
FieldList,
|
||||||
DateField,
|
DateField,
|
||||||
SelectField)
|
SelectField)
|
||||||
from wtforms.fields.html5 import EmailField, TelField
|
from wtforms.fields.html5 import EmailField, TelField, SearchField
|
||||||
from wtforms.validators import (DataRequired, Email, Length, Regexp, Optional)
|
from wtforms.validators import (DataRequired, Email, Length, Regexp, Optional)
|
||||||
|
|
||||||
from app.main.validators import (Blacklist, CsvFileValidator, ValidGovEmail, NoCommasInPlaceHolders, OnlyGSMCharacters)
|
from app.main.validators import (Blacklist, CsvFileValidator, ValidGovEmail, NoCommasInPlaceHolders, OnlyGSMCharacters)
|
||||||
@@ -288,7 +288,18 @@ class EmailTemplateForm(BaseTemplateForm):
|
|||||||
|
|
||||||
|
|
||||||
class LetterTemplateForm(EmailTemplateForm):
|
class LetterTemplateForm(EmailTemplateForm):
|
||||||
pass
|
|
||||||
|
subject = TextAreaField(
|
||||||
|
u'Title',
|
||||||
|
validators=[DataRequired(message="Can’t be empty")])
|
||||||
|
|
||||||
|
template_content = TextAreaField(
|
||||||
|
u'Body',
|
||||||
|
validators=[
|
||||||
|
DataRequired(message="Can’t be empty"),
|
||||||
|
NoCommasInPlaceHolders()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ForgotPasswordForm(Form):
|
class ForgotPasswordForm(Form):
|
||||||
@@ -591,3 +602,8 @@ class ChooseTemplateType(Form):
|
|||||||
('sms', 'Text message'),
|
('sms', 'Text message'),
|
||||||
('letter', 'Letter') if include_letters else None
|
('letter', 'Letter') if include_letters else None
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class SearchTemplatesForm(Form):
|
||||||
|
|
||||||
|
search = SearchField('Search by name')
|
||||||
|
|||||||
@@ -190,19 +190,6 @@ def send_test(service_id, template_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@main.route("/services/<service_id>/send/<template_id>/from-api", methods=['GET'])
|
|
||||||
@login_required
|
|
||||||
def send_from_api(service_id, template_id):
|
|
||||||
return render_template(
|
|
||||||
'views/send-from-api.html',
|
|
||||||
template=get_template(
|
|
||||||
service_api_client.get_service_template(service_id, template_id)['data'],
|
|
||||||
current_service,
|
|
||||||
letter_preview_url=url_for('.view_template', service_id=service_id, template_id=template_id)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _check_messages(service_id, template_type, upload_id, letters_as_pdf=False):
|
def _check_messages(service_id, template_type, upload_id, letters_as_pdf=False):
|
||||||
|
|
||||||
if not session.get('upload_data'):
|
if not session.get('upload_data'):
|
||||||
|
|||||||
@@ -13,7 +13,13 @@ from notifications_python_client.errors import HTTPError
|
|||||||
|
|
||||||
from app.main import main
|
from app.main import main
|
||||||
from app.utils import user_has_permissions, get_template, png_from_pdf
|
from app.utils import user_has_permissions, get_template, png_from_pdf
|
||||||
from app.main.forms import ChooseTemplateType, SMSTemplateForm, EmailTemplateForm, LetterTemplateForm
|
from app.main.forms import (
|
||||||
|
ChooseTemplateType,
|
||||||
|
SMSTemplateForm,
|
||||||
|
EmailTemplateForm,
|
||||||
|
LetterTemplateForm,
|
||||||
|
SearchTemplatesForm,
|
||||||
|
)
|
||||||
from app.main.views.send import get_example_csv_rows
|
from app.main.views.send import get_example_csv_rows
|
||||||
from app import service_api_client, current_service, template_statistics_client
|
from app import service_api_client, current_service, template_statistics_client
|
||||||
|
|
||||||
@@ -44,15 +50,8 @@ page_headings = {
|
|||||||
def choose_template(service_id):
|
def choose_template(service_id):
|
||||||
return render_template(
|
return render_template(
|
||||||
'views/templates/choose.html',
|
'views/templates/choose.html',
|
||||||
templates=[
|
templates=service_api_client.get_service_templates(service_id)['data'],
|
||||||
get_template(
|
search_form=SearchTemplatesForm(),
|
||||||
template,
|
|
||||||
current_service,
|
|
||||||
letter_preview_url=url_for('.view_template', service_id=service_id, template_id=template['id']),
|
|
||||||
)
|
|
||||||
for template in service_api_client.get_service_templates(service_id)['data']
|
|
||||||
if should_show_template(template['template_type'])
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +72,8 @@ def view_template(service_id, template_id):
|
|||||||
service_api_client.get_service_template(service_id, template_id)['data'],
|
service_api_client.get_service_template(service_id, template_id)['data'],
|
||||||
current_service,
|
current_service,
|
||||||
expand_emails=True,
|
expand_emails=True,
|
||||||
letter_preview_url=url_for('.view_template', service_id=service_id, template_id=template_id)
|
letter_preview_url=url_for('.view_template', service_id=service_id, template_id=template_id),
|
||||||
|
show_recipient=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -178,6 +178,22 @@ def add_template_by_type(service_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
|
|
||||||
|
if form.template_type.data == 'letter':
|
||||||
|
blank_letter = service_api_client.create_service_template(
|
||||||
|
'Untitled',
|
||||||
|
'letter',
|
||||||
|
'Content',
|
||||||
|
service_id,
|
||||||
|
'Title',
|
||||||
|
'normal',
|
||||||
|
)
|
||||||
|
return redirect(url_for(
|
||||||
|
'.view_template',
|
||||||
|
service_id=service_id,
|
||||||
|
template_id=blank_letter['data']['id'],
|
||||||
|
))
|
||||||
|
|
||||||
return redirect(url_for(
|
return redirect(url_for(
|
||||||
'.add_service_template',
|
'.add_service_template',
|
||||||
service_id=service_id,
|
service_id=service_id,
|
||||||
@@ -202,7 +218,7 @@ def add_service_template(service_id, template_type):
|
|||||||
if form.process_type.data == 'priority':
|
if form.process_type.data == 'priority':
|
||||||
abort_403_if_not_admin_user()
|
abort_403_if_not_admin_user()
|
||||||
try:
|
try:
|
||||||
service_api_client.create_service_template(
|
new_template = service_api_client.create_service_template(
|
||||||
form.name.data,
|
form.name.data,
|
||||||
template_type,
|
template_type,
|
||||||
form.template_content.data,
|
form.template_content.data,
|
||||||
@@ -221,7 +237,7 @@ def add_service_template(service_id, template_type):
|
|||||||
raise e
|
raise e
|
||||||
else:
|
else:
|
||||||
return redirect(
|
return redirect(
|
||||||
url_for('.choose_template', service_id=service_id)
|
url_for('.view_template', service_id=service_id, template_id=new_template['data']['id'])
|
||||||
)
|
)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
|
|||||||
@@ -19,41 +19,43 @@
|
|||||||
<a href="{{ url_for('.create_api_key', service_id=current_service.id) }}" class="button align-with-heading">Create an API key</a>
|
<a href="{{ url_for('.create_api_key', service_id=current_service.id) }}" class="button align-with-heading">Create an API key</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% call(item, row_number) list_table(
|
<div class="body-copy-table">
|
||||||
keys,
|
{% call(item, row_number) list_table(
|
||||||
empty_message="You haven’t created any API keys yet",
|
keys,
|
||||||
caption="API keys",
|
empty_message="You haven’t created any API keys yet",
|
||||||
caption_visible=false,
|
caption="API keys",
|
||||||
field_headings=[
|
caption_visible=false,
|
||||||
'API keys',
|
field_headings=[
|
||||||
'Action'
|
'API keys',
|
||||||
],
|
'Action'
|
||||||
field_headings_visible=False
|
],
|
||||||
) %}
|
field_headings_visible=False
|
||||||
{% call field() %}
|
) %}
|
||||||
<div class="file-list">
|
{% call field() %}
|
||||||
{{ item.name }}
|
<div class="file-list">
|
||||||
<span class="file-list-hint">
|
{{ item.name }}
|
||||||
{% if item.key_type == 'normal' %}
|
<div class="hint">
|
||||||
Live – sends to anyone
|
{% if item.key_type == 'normal' %}
|
||||||
{% elif item.key_type == 'team' %}
|
Live – sends to anyone
|
||||||
Team and whitelist – limits who you can send to
|
{% elif item.key_type == 'team' %}
|
||||||
{% elif item.key_type == 'test' %}
|
Team and whitelist – limits who you can send to
|
||||||
Test – pretends to send messages
|
{% elif item.key_type == 'test' %}
|
||||||
{% endif %}
|
Test – pretends to send messages
|
||||||
</span>
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endcall %}
|
||||||
|
{% if item.expiry_date %}
|
||||||
|
{% call field(align='right') %}
|
||||||
|
<span class='hint'>Revoked {{ item.expiry_date|format_datetime_short }}</span>
|
||||||
|
{% endcall %}
|
||||||
|
{% else %}
|
||||||
|
{% call field(align='right', status='error') %}
|
||||||
|
<a href='{{ url_for('.revoke_api_key', service_id=current_service.id, key_id=item.id) }}'>Revoke</a>
|
||||||
|
{% endcall %}
|
||||||
|
{% endif %}
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
{% if item.expiry_date %}
|
</div>
|
||||||
{% call field(align='right') %}
|
|
||||||
<span class='hint'>Revoked {{ item.expiry_date|format_datetime_short }}</span>
|
|
||||||
{% endcall %}
|
|
||||||
{% else %}
|
|
||||||
{% call field(align='right', status='error') %}
|
|
||||||
<a href='{{ url_for('.revoke_api_key', service_id=current_service.id, key_id=item.id) }}'>Revoke</a>
|
|
||||||
{% endcall %}
|
|
||||||
{% endif %}
|
|
||||||
{% endcall %}
|
|
||||||
|
|
||||||
{{ page_footer(
|
{{ page_footer(
|
||||||
secondary_link=url_for('.api_integration', service_id=current_service.id),
|
secondary_link=url_for('.api_integration', service_id=current_service.id),
|
||||||
|
|||||||
@@ -175,7 +175,11 @@
|
|||||||
wrapping_class='bottom-gutter-2-3'
|
wrapping_class='bottom-gutter-2-3'
|
||||||
) }}
|
) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% 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='') }}" />
|
<input type="submit" class="button" value="Send {{ count_of_recipients }} {{ message_count_label(count_of_recipients, template.template_type, suffix='') }}" />
|
||||||
|
{% else %}
|
||||||
|
<a href="#" class="heading-medium">Download as PDF</a>
|
||||||
|
{% endif %}
|
||||||
<a href="{{ back_link }}" class="page-footer-back-link">Back</a>
|
<a href="{{ back_link }}" class="page-footer-back-link">Back</a>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
{% extends "withnav_template.html" %}
|
|
||||||
{% from "components/api-key.html" import api_key %}
|
|
||||||
|
|
||||||
{% block service_page_title %}
|
|
||||||
API info
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block maincolumn_content %}
|
|
||||||
|
|
||||||
<h1 class="heading-large">
|
|
||||||
API info
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
{{ template|string }}
|
|
||||||
|
|
||||||
<div class="bottom-gutter">
|
|
||||||
{{ api_key(template.id, name="Template ID", thing='template ID') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -13,11 +13,17 @@
|
|||||||
|
|
||||||
{% block maincolumn_content %}
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
|
<h1 class="heading-large">
|
||||||
{% if request.args['help'] %}
|
{% if request.args['help'] %}
|
||||||
<h1 class="heading-large">Example text message</h1>
|
Example text message
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1 class="heading-large">Send yourself a test</h1>
|
{% if template.template_type == 'letter' %}
|
||||||
|
Generate preview
|
||||||
|
{% else %}
|
||||||
|
Send yourself a test
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</h1>
|
||||||
|
|
||||||
{{ template|string }}
|
{{ template|string }}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<h1 class="heading-large">Settings</h1>
|
<h1 class="heading-large">Settings</h1>
|
||||||
|
|
||||||
<div class="bottom-gutter-3-2">
|
<div class="bottom-gutter-3-2 body-copy-table">
|
||||||
|
|
||||||
{% call mapping_table(
|
{% call mapping_table(
|
||||||
caption='Settings',
|
caption='Settings',
|
||||||
|
|||||||
@@ -1,25 +1,42 @@
|
|||||||
<div class="column-two-thirds">
|
<div class="column-whole">
|
||||||
{{ template|string }}
|
|
||||||
</div>
|
|
||||||
<div class="column-one-third">
|
|
||||||
{% if template._template.archived %}
|
{% if template._template.archived %}
|
||||||
<div class="message-updated-at">
|
<p class="hint">
|
||||||
This template was deleted<br/>{{ template._template.updated_at|format_date_normal }}
|
This template was deleted {{ template._template.updated_at|format_datetime_relative }}.
|
||||||
</div>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="message-use-links{% if show_title %}-with-title{% endif %}">
|
<div class="bottom-gutter-2-3">
|
||||||
{% if current_user.has_permissions(permissions=['send_texts', 'send_emails', 'send_letters']) %}
|
<div class="grid-row">
|
||||||
<a href="{{ url_for(".send_messages", service_id=current_service.id, template_id=template.id) }}" class="primary">
|
{% if current_user.has_permissions(permissions=['send_texts', 'send_emails', 'send_letters']) %}
|
||||||
Upload recipients
|
<div class="{{ 'column-half' if template.template_type == 'letter' else 'column-third' }}">
|
||||||
</a>
|
<a href="{{ url_for(".send_messages", service_id=current_service.id, template_id=template.id) }}" class="pill-separate-item">
|
||||||
<a href="{{ url_for(".send_test", service_id=current_service.id, template_id=template.id) }}">
|
Upload recipients
|
||||||
Send yourself a test
|
</a>
|
||||||
</a>
|
</div>
|
||||||
{% endif %}
|
<div class="{{ 'column-half' if template.template_type == 'letter' else 'column-third' }}">
|
||||||
{% if current_user.has_permissions(permissions=['manage_templates'], admin_override=True) %}
|
<a href="{{ url_for(".send_test", service_id=current_service.id, template_id=template.id) }}" class="pill-separate-item">
|
||||||
<a href="{{ url_for(".edit_service_template", service_id=current_service.id, template_id=template.id) }}">Edit template</a>
|
{{ 'Generate preview' if template.template_type == 'letter' else 'Send yourself a test' }}
|
||||||
{% endif %}
|
</a>
|
||||||
<a href="{{ url_for(".send_from_api", service_id=current_service.id, template_id=template.id) }}">API info</a>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if
|
||||||
|
current_user.has_permissions(permissions=['manage_templates'], admin_override=True) and
|
||||||
|
template.template_type != 'letter'
|
||||||
|
%}
|
||||||
|
<div class="column-one-third">
|
||||||
|
<a href="{{ url_for(".edit_service_template", service_id=current_service.id, template_id=template.id) }}" class="pill-separate-item">
|
||||||
|
Edit template
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
<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_set_letter_contact_block", service_id=current_service.id) }}" class="edit-template-link-letter-contact">Edit</a>
|
||||||
|
<a href="#" class="edit-template-link-letter-address">Edit</a>
|
||||||
|
{% endif %}
|
||||||
|
{{ template|string }}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
<div class="column-whole">
|
<div class="column-whole">
|
||||||
<h2 class="message-name">{{ template.name }}</h2>
|
<h2 class="message-name">{{ template.name }}</h2>
|
||||||
|
<p class="hint">
|
||||||
|
{% if template.get_raw('version', 1) > 1 %}
|
||||||
|
Edit made {% if template.get_raw('updated_at', None) %}{{ template.get_raw('updated_at')|format_datetime_normal }}{% endif %}
|
||||||
|
{% else %}
|
||||||
|
Created
|
||||||
|
{% if template.get_raw('created_at', None) %}{{ template.get_raw('created_at')|format_datetime_normal }}{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
by {{ template.get_raw('created_by').name }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column-two-thirds">
|
<div class="column-whole">
|
||||||
{{ template|string }}
|
{{ template|string }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column-one-third">
|
|
||||||
<div class="message-use-links">
|
|
||||||
{% if template.get_raw('version', 1) > 1 %}
|
|
||||||
{% if template.get_raw('updated_at', None) %}{{ template.get_raw('updated_at')|format_datetime_normal }}{% endif %}
|
|
||||||
{% else %}
|
|
||||||
Created<br/>{% if template.get_raw('created_at', None) %}{{ template.get_raw('created_at')|format_datetime_normal }}{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
<br/>by {{ template.get_raw('created_by').name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
{% from "components/message-count-label.html" import message_count_label %}
|
||||||
|
{% from "components/textbox.html" import textbox %}
|
||||||
|
|
||||||
{% extends "withnav_template.html" %}
|
{% extends "withnav_template.html" %}
|
||||||
|
|
||||||
{% block service_page_title %}
|
{% block service_page_title %}
|
||||||
@@ -33,7 +36,7 @@
|
|||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<div class="grid-row">
|
<div class="grid-row bottom-gutter-1-2">
|
||||||
<div class="column-two-thirds">
|
<div class="column-two-thirds">
|
||||||
<h1 class="heading-large">Templates</h1>
|
<h1 class="heading-large">Templates</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,19 +47,29 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid-row">
|
{% if templates|length > 7 %}
|
||||||
|
<div data-module="autofocus">
|
||||||
|
<div class="live-search" data-module="live-search" data-targets="#template-list .column-whole">
|
||||||
|
{{ textbox(
|
||||||
|
search_form.search,
|
||||||
|
width='1-1'
|
||||||
|
) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<nav class="grid-row" id=template-list>
|
||||||
{% for template in templates %}
|
{% for template in templates %}
|
||||||
<div class="column-whole">
|
<div class="column-whole">
|
||||||
<h2 class="message-name">{{ template.name }}</h2>
|
<h2 class="message-name">
|
||||||
{% if template.get_raw('updated_at', None) %}
|
<a href="{{ url_for('.view_template', service_id=current_service.id, template_id=template.id) }}">{{ template.name }}</a>
|
||||||
<p class="message-updated-at">
|
</h2>
|
||||||
Edited {{ template.get_raw('updated_at', None)|format_date_short }} <a href="{{ url_for('.view_template_versions', service_id=current_service.id, template_id=template.id) }}">see previous versions</a>
|
<p class="hint bottom-gutter-1-3">
|
||||||
</p>
|
{{ message_count_label(1, template.template_type, suffix='')|capitalize }} template
|
||||||
{% endif %}
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% include 'views/templates/_template.html' %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</nav>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{% extends "withnav_template.html" %}
|
{% extends "withnav_template.html" %}
|
||||||
{% from "components/page-footer.html" import page_footer %}
|
{% from "components/page-footer.html" import page_footer %}
|
||||||
{% from "components/textbox.html" import textbox %}
|
{% from "components/textbox.html" import textbox %}
|
||||||
|
{% from "components/api-key.html" import api_key %}
|
||||||
|
|
||||||
{% block service_page_title %}
|
{% block service_page_title %}
|
||||||
{{ template.name }}
|
{{ template.name }}
|
||||||
@@ -17,9 +18,17 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{ page_footer(
|
<div class="bottom-gutter">
|
||||||
secondary_link=url_for('.choose_template', service_id=current_service.id),
|
{{ api_key(template.id, name="Template ID", thing='template ID') }}
|
||||||
secondary_link_text='All templates'
|
</div>
|
||||||
) }}
|
|
||||||
|
{% if template._template.updated_at %}
|
||||||
|
<div class="bottom-gutter-2">
|
||||||
|
<h2 class="heading-small">Last edited {{ template._template.updated_at|format_datetime_relative }}</h2>
|
||||||
|
<p>
|
||||||
|
<a href="{{ url_for('.view_template_versions', service_id=current_service.id, template_id=template.id) }}">See previous versions</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
<a href="{{ url_for('main.choose_service') }}" class="navigation-service-switch">Switch service</a>
|
<a href="{{ url_for('main.choose_service') }}" class="navigation-service-switch">Switch service</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="column-one-third">
|
<div class="column-one-quarter">
|
||||||
{% include "main_nav.html" %}
|
{% include "main_nav.html" %}
|
||||||
</div>
|
</div>
|
||||||
<main role="main" class="column-two-thirds column-main">
|
<main role="main" class="column-three-quarters column-main">
|
||||||
{% include 'flash_messages.html' %}
|
{% include 'flash_messages.html' %}
|
||||||
{% block maincolumn_content %}{% endblock %}
|
{% block maincolumn_content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ def png_from_pdf(pdf_endpoint):
|
|||||||
output = BytesIO()
|
output = BytesIO()
|
||||||
with Image(
|
with Image(
|
||||||
blob=pdf_endpoint.get_data(),
|
blob=pdf_endpoint.get_data(),
|
||||||
resolution=96,
|
resolution=150,
|
||||||
) as image:
|
) as image:
|
||||||
with image.convert('png') as converted:
|
with image.convert('png') as converted:
|
||||||
converted.save(file=output)
|
converted.save(file=output)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ gulp.task('javascripts', () => gulp
|
|||||||
paths.src + 'javascripts/radioSelect.js',
|
paths.src + 'javascripts/radioSelect.js',
|
||||||
paths.src + 'javascripts/updateContent.js',
|
paths.src + 'javascripts/updateContent.js',
|
||||||
paths.src + 'javascripts/listEntry.js',
|
paths.src + 'javascripts/listEntry.js',
|
||||||
|
paths.src + 'javascripts/liveSearch.js',
|
||||||
paths.src + 'javascripts/main.js'
|
paths.src + 'javascripts/main.js'
|
||||||
])
|
])
|
||||||
.pipe(plugins.prettyerror())
|
.pipe(plugins.prettyerror())
|
||||||
|
|||||||
@@ -316,25 +316,6 @@ def test_send_test_sms_message_with_placeholders(
|
|||||||
mock_s3_upload.assert_called_with(fake_uuid, expected_data, 'eu-west-1')
|
mock_s3_upload.assert_called_with(fake_uuid, expected_data, 'eu-west-1')
|
||||||
|
|
||||||
|
|
||||||
def test_api_info_page(
|
|
||||||
logged_in_client,
|
|
||||||
mocker,
|
|
||||||
api_user_active,
|
|
||||||
mock_login,
|
|
||||||
mock_get_service,
|
|
||||||
mock_get_service_email_template,
|
|
||||||
mock_s3_upload,
|
|
||||||
mock_has_permissions,
|
|
||||||
fake_uuid
|
|
||||||
):
|
|
||||||
response = logged_in_client.get(
|
|
||||||
url_for('main.send_from_api', service_id=fake_uuid, template_id=fake_uuid),
|
|
||||||
follow_redirects=True
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert 'API info' in response.get_data(as_text=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_download_example_csv(
|
def test_download_example_csv(
|
||||||
logged_in_client,
|
logged_in_client,
|
||||||
mocker,
|
mocker,
|
||||||
@@ -664,132 +645,6 @@ def test_route_invalid_permissions(
|
|||||||
service_one)
|
service_one)
|
||||||
|
|
||||||
|
|
||||||
def test_route_choose_template_manage_service_permissions(
|
|
||||||
mocker,
|
|
||||||
app_,
|
|
||||||
client,
|
|
||||||
api_user_active,
|
|
||||||
service_one,
|
|
||||||
mock_login,
|
|
||||||
mock_get_user,
|
|
||||||
mock_get_service,
|
|
||||||
mock_check_verify_code,
|
|
||||||
mock_get_service_templates,
|
|
||||||
mock_get_jobs,
|
|
||||||
):
|
|
||||||
template_id = mock_get_service_templates(service_one['id'])['data'][0]['id']
|
|
||||||
resp = validate_route_permission(
|
|
||||||
mocker,
|
|
||||||
app_,
|
|
||||||
"GET",
|
|
||||||
200,
|
|
||||||
url_for(
|
|
||||||
'main.choose_template',
|
|
||||||
service_id=service_one['id'],
|
|
||||||
),
|
|
||||||
['manage_users', 'manage_templates', 'manage_settings'],
|
|
||||||
api_user_active,
|
|
||||||
service_one)
|
|
||||||
page = resp.get_data(as_text=True)
|
|
||||||
assert url_for(
|
|
||||||
"main.send_messages",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) not in page
|
|
||||||
assert url_for(
|
|
||||||
"main.send_test",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) not in page
|
|
||||||
assert url_for(
|
|
||||||
"main.edit_service_template",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) in page
|
|
||||||
|
|
||||||
|
|
||||||
def test_route_choose_template_send_messages_permissions(
|
|
||||||
mocker,
|
|
||||||
app_,
|
|
||||||
client,
|
|
||||||
active_user_with_permissions,
|
|
||||||
service_one,
|
|
||||||
mock_get_service,
|
|
||||||
mock_check_verify_code,
|
|
||||||
mock_get_service_templates,
|
|
||||||
mock_get_jobs,
|
|
||||||
):
|
|
||||||
template_id = None
|
|
||||||
for temp in mock_get_service_templates(service_one['id'])['data']:
|
|
||||||
if temp['template_type'] == 'sms':
|
|
||||||
template_id = temp['id']
|
|
||||||
assert template_id
|
|
||||||
resp = validate_route_permission(
|
|
||||||
mocker,
|
|
||||||
app_,
|
|
||||||
"GET",
|
|
||||||
200,
|
|
||||||
url_for(
|
|
||||||
'main.choose_template',
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_type='sms'),
|
|
||||||
['send_texts', 'send_emails', 'send_letters'],
|
|
||||||
active_user_with_permissions,
|
|
||||||
service_one)
|
|
||||||
page = resp.get_data(as_text=True)
|
|
||||||
assert url_for(
|
|
||||||
"main.send_messages",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) in page
|
|
||||||
assert url_for(
|
|
||||||
"main.edit_service_template",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) not in page
|
|
||||||
|
|
||||||
|
|
||||||
def test_route_choose_template_manage_api_keys_permissions(
|
|
||||||
mocker,
|
|
||||||
app_,
|
|
||||||
client,
|
|
||||||
api_user_active,
|
|
||||||
service_one,
|
|
||||||
mock_get_user,
|
|
||||||
mock_get_service,
|
|
||||||
mock_check_verify_code,
|
|
||||||
mock_get_service_templates,
|
|
||||||
mock_get_jobs,
|
|
||||||
):
|
|
||||||
template_id = None
|
|
||||||
for temp in mock_get_service_templates(service_one['id'])['data']:
|
|
||||||
if temp['template_type'] == 'sms':
|
|
||||||
template_id = temp['id']
|
|
||||||
assert template_id
|
|
||||||
resp = validate_route_permission(
|
|
||||||
mocker,
|
|
||||||
app_,
|
|
||||||
"GET",
|
|
||||||
200,
|
|
||||||
url_for(
|
|
||||||
'main.choose_template',
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_type='sms'),
|
|
||||||
['manage_api_keys'],
|
|
||||||
api_user_active,
|
|
||||||
service_one)
|
|
||||||
page = resp.get_data(as_text=True)
|
|
||||||
assert url_for(
|
|
||||||
"main.send_test",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) not in page
|
|
||||||
assert url_for(
|
|
||||||
"main.edit_service_template",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id) not in page
|
|
||||||
page = BeautifulSoup(resp.data.decode('utf-8'), 'html.parser')
|
|
||||||
links = page.findAll('a', href=re.compile('^' + url_for(
|
|
||||||
"main.send_from_api",
|
|
||||||
service_id=service_one['id'],
|
|
||||||
template_id=template_id)))
|
|
||||||
assert len(links) == 1
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'extra_args,expected_url',
|
'extra_args,expected_url',
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -33,6 +33,75 @@ def test_should_show_page_for_one_template(
|
|||||||
mock_get_service_template.assert_called_with(service_one['id'], template_id)
|
mock_get_service_template.assert_called_with(service_one['id'], template_id)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('permissions, links_to_be_shown', [
|
||||||
|
(
|
||||||
|
['view_activity'],
|
||||||
|
[]
|
||||||
|
),
|
||||||
|
(
|
||||||
|
['manage_templates'],
|
||||||
|
['.edit_service_template']
|
||||||
|
),
|
||||||
|
(
|
||||||
|
['send_texts', 'send_emails', 'send_letters'],
|
||||||
|
['.send_messages', '.send_test']
|
||||||
|
),
|
||||||
|
(
|
||||||
|
['send_texts', 'send_emails', 'send_letters', 'manage_templates'],
|
||||||
|
['.send_messages', '.send_test', '.edit_service_template']
|
||||||
|
),
|
||||||
|
])
|
||||||
|
def test_should_be_able_to_view_a_template_with_links(
|
||||||
|
client,
|
||||||
|
mock_get_service_template,
|
||||||
|
active_user_with_permissions,
|
||||||
|
mocker,
|
||||||
|
service_one,
|
||||||
|
fake_uuid,
|
||||||
|
permissions,
|
||||||
|
links_to_be_shown,
|
||||||
|
):
|
||||||
|
active_user_with_permissions._permissions[service_one['id']] = permissions
|
||||||
|
client.login(active_user_with_permissions, mocker, service_one)
|
||||||
|
|
||||||
|
response = client.get(url_for(
|
||||||
|
'.view_template',
|
||||||
|
service_id=service_one['id'],
|
||||||
|
template_id=fake_uuid
|
||||||
|
))
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
links_in_page = page.select('.pill-separate-item')
|
||||||
|
|
||||||
|
assert len(links_in_page) == len(links_to_be_shown)
|
||||||
|
|
||||||
|
for index, link_to_be_shown in enumerate(links_to_be_shown):
|
||||||
|
assert links_in_page[index]['href'] == url_for(
|
||||||
|
link_to_be_shown,
|
||||||
|
service_id=service_one['id'],
|
||||||
|
template_id=fake_uuid,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_should_show_template_id_on_template_page(
|
||||||
|
logged_in_client,
|
||||||
|
mock_get_service_template,
|
||||||
|
service_one,
|
||||||
|
fake_uuid,
|
||||||
|
):
|
||||||
|
|
||||||
|
response = logged_in_client.get(url_for(
|
||||||
|
'.view_template',
|
||||||
|
service_id=service_one['id'],
|
||||||
|
template_id=fake_uuid))
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
assert page.select('.api-key-key')[0].text == fake_uuid
|
||||||
|
|
||||||
|
|
||||||
def test_should_show_sms_template_with_downgraded_unicode_characters(
|
def test_should_show_sms_template_with_downgraded_unicode_characters(
|
||||||
logged_in_client,
|
logged_in_client,
|
||||||
mocker,
|
mocker,
|
||||||
@@ -513,10 +582,10 @@ def test_should_show_page_for_a_deleted_template(
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
content = response.get_data(as_text=True)
|
content = response.get_data(as_text=True)
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
assert url_for("main.edit_service_template", service_id=fake_uuid, template_id=fake_uuid) not in content
|
assert url_for("main.edit_service_template", service_id=fake_uuid, template_id=fake_uuid) not in content
|
||||||
assert url_for("main.send_from_api", service_id=fake_uuid, template_id=fake_uuid) not in content
|
|
||||||
assert url_for("main.send_test", service_id=fake_uuid, template_id=fake_uuid) not in content
|
assert url_for("main.send_test", service_id=fake_uuid, template_id=fake_uuid) not in content
|
||||||
assert "This template was deleted<br/>1 January 2016" in content
|
assert page.select('p.hint')[0].text.strip() == 'This template was deleted today at 3:00pm.'
|
||||||
|
|
||||||
mock_get_deleted_template.assert_called_with(service_id, template_id)
|
mock_get_deleted_template.assert_called_with(service_id, template_id)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user