mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-02-06 03:13:42 -05:00
Move code for rendering messages/templates → utils
Utils is better structured to handle the logic of what thing to show for what template type, especially now that what we show for different template types in different contexts has diverged significantly. See https://github.com/alphagov/notifications-utils/commit/6b39c1a for an example of this code moving into utils Depends on and implements: https://github.com/alphagov/notifications-utils/pull/84 The main reason for doing this is to get Paul’s fix for the misaligned CSV columns: https://github.com/alphagov/notifications-utils/pull/87
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
.sms-message-wrapper {
|
||||
|
||||
width: 100%;
|
||||
max-width: 410px;
|
||||
box-sizing: border-box;
|
||||
padding: $gutter-half;
|
||||
background: $panel-colour;
|
||||
|
||||
@@ -28,7 +28,7 @@ from app.main.uploader import (
|
||||
s3download
|
||||
)
|
||||
from app import job_api_client, service_api_client, current_service, user_api_client
|
||||
from app.utils import user_has_permissions, get_errors_for_csv, Spreadsheet, get_help_argument
|
||||
from app.utils import user_has_permissions, get_errors_for_csv, Spreadsheet, get_help_argument, get_renderer
|
||||
|
||||
|
||||
def get_page_headings(template_type):
|
||||
@@ -90,8 +90,7 @@ def choose_template(service_id, template_type):
|
||||
templates=[
|
||||
Template(
|
||||
template,
|
||||
prefix=current_service['name'],
|
||||
sms_sender=current_service['sms_sender']
|
||||
renderer=get_renderer(template_type, current_service, show_recipient=False)
|
||||
) for template in service_api_client.get_service_templates(service_id)['data']
|
||||
if template['template_type'] == template_type
|
||||
],
|
||||
@@ -105,10 +104,9 @@ def choose_template(service_id, template_type):
|
||||
@user_has_permissions('send_texts', 'send_emails', 'send_letters')
|
||||
def send_messages(service_id, template_id):
|
||||
template = Template(
|
||||
service_api_client.get_service_template(service_id, template_id)['data'],
|
||||
prefix=current_service['name'],
|
||||
sms_sender=current_service['sms_sender']
|
||||
service_api_client.get_service_template(service_id, template_id)['data']
|
||||
)
|
||||
template.renderer = get_renderer(template.template_type, current_service, show_recipient=True)
|
||||
|
||||
form = CsvUploadForm()
|
||||
if form.validate_on_submit():
|
||||
@@ -169,6 +167,8 @@ def send_test(service_id, template_id):
|
||||
sms_sender=current_service['sms_sender']
|
||||
)
|
||||
|
||||
template.renderer = get_renderer(template.template_type, current_service, show_recipient=True)
|
||||
|
||||
if len(template.placeholders) == 0 or request.method == 'POST':
|
||||
upload_id = s3upload(
|
||||
service_id,
|
||||
@@ -237,11 +237,11 @@ def check_messages(service_id, template_type, upload_id):
|
||||
service_api_client.get_service_template(
|
||||
service_id,
|
||||
session['upload_data'].get('template_id')
|
||||
)['data'],
|
||||
prefix=current_service['name'],
|
||||
sms_sender=current_service['sms_sender']
|
||||
)['data']
|
||||
)
|
||||
|
||||
template.renderer = get_renderer(template_type, current_service, show_recipient=True)
|
||||
|
||||
recipients = RecipientCSV(
|
||||
contents,
|
||||
template_type=template.template_type,
|
||||
|
||||
@@ -10,7 +10,7 @@ from notifications_utils.recipients import first_column_headings
|
||||
from notifications_python_client.errors import HTTPError
|
||||
|
||||
from app.main import main
|
||||
from app.utils import user_has_permissions
|
||||
from app.utils import user_has_permissions, get_renderer
|
||||
from app.main.forms import SMSTemplateForm, EmailTemplateForm, LetterTemplateForm
|
||||
from app.main.views.send import get_example_csv_rows
|
||||
from app import service_api_client, current_service, template_statistics_client
|
||||
@@ -39,13 +39,15 @@ page_headings = {
|
||||
admin_override=True, any_=True
|
||||
)
|
||||
def view_template(service_id, template_id):
|
||||
template = Template(
|
||||
service_api_client.get_service_template(service_id, template_id)['data']
|
||||
)
|
||||
template.renderer = get_renderer(
|
||||
template.template_type, current_service, show_recipient=False, expand_emails=True
|
||||
)
|
||||
return render_template(
|
||||
'views/templates/template.html',
|
||||
template=Template(
|
||||
service_api_client.get_service_template(service_id, template_id)['data'],
|
||||
prefix=current_service['name'],
|
||||
sms_sender=current_service['sms_sender']
|
||||
)
|
||||
template=template
|
||||
)
|
||||
|
||||
|
||||
@@ -61,13 +63,15 @@ def view_template(service_id, template_id):
|
||||
any_=True
|
||||
)
|
||||
def view_template_version(service_id, template_id, version):
|
||||
template = Template(
|
||||
service_api_client.get_service_template(service_id, template_id, version)['data']
|
||||
)
|
||||
template.renderer = get_renderer(
|
||||
template.template_type, current_service, show_recipient=False, expand_emails=True
|
||||
)
|
||||
return render_template(
|
||||
'views/templates/template_history.html',
|
||||
template=Template(
|
||||
service_api_client.get_service_template(service_id, template_id, version)['data'],
|
||||
prefix=current_service['name'],
|
||||
sms_sender=current_service['sms_sender']
|
||||
)
|
||||
template=template
|
||||
)
|
||||
|
||||
|
||||
@@ -227,19 +231,18 @@ def delete_service_template(service_id, template_id):
|
||||
any_=True
|
||||
)
|
||||
def view_template_versions(service_id, template_id):
|
||||
|
||||
versions = []
|
||||
for template in service_api_client.get_service_template_versions(service_id, template_id)['data']:
|
||||
template = Template(template)
|
||||
template.renderer = get_renderer(
|
||||
template.template_type, current_service, show_recipient=False, expand_emails=True
|
||||
)
|
||||
versions.append(template)
|
||||
|
||||
return render_template(
|
||||
'views/templates/choose_history.html',
|
||||
template=Template(
|
||||
service_api_client.get_service_template(service_id, template_id)['data'],
|
||||
prefix=current_service['name']
|
||||
),
|
||||
versions=[
|
||||
Template(
|
||||
template,
|
||||
prefix=current_service['name'],
|
||||
sms_sender=current_service['sms_sender']
|
||||
) for template in service_api_client.get_service_template_versions(service_id, template_id)['data']
|
||||
]
|
||||
versions=versions
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
{% macro email_message(
|
||||
subject,
|
||||
body,
|
||||
from_name=None,
|
||||
from_address=None,
|
||||
recipient=None,
|
||||
id=None,
|
||||
show_placeholder_for_recipient=False,
|
||||
show_id=False,
|
||||
expanded=False
|
||||
) %}
|
||||
<div class="email-message">
|
||||
{% if from_name or subject %}
|
||||
<table class="email-message-meta">
|
||||
<tbody>
|
||||
{% if from_name and from_address %}
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<td>
|
||||
{{ from_name }} <{{ from_address }}>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if recipient is not none %}
|
||||
<tr>
|
||||
<th>To</th>
|
||||
<td>
|
||||
{% if show_placeholder_for_recipient %}
|
||||
<span class="placeholder-no-brackets">
|
||||
email address
|
||||
</span>
|
||||
{% else %}
|
||||
{{ recipient }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if subject %}
|
||||
<tr class="email-message-meta">
|
||||
<th>Subject</th>
|
||||
<td>
|
||||
{{ subject }}
|
||||
</td>
|
||||
</div>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
<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">
|
||||
{% endif %}
|
||||
{{ body }}
|
||||
{% if not expanded %}
|
||||
</div>
|
||||
<div class='toggle' tabindex='0'>...<span class='visually-hidden'>show full email</span></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -1,7 +0,0 @@
|
||||
{% macro letter(
|
||||
body
|
||||
) %}
|
||||
<div class="letter">
|
||||
{{ body }}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -1,37 +0,0 @@
|
||||
{% macro sms_message(
|
||||
body,
|
||||
recipient=None,
|
||||
id=None,
|
||||
from=None,
|
||||
version=1,
|
||||
updated_at=None,
|
||||
versions_url=None,
|
||||
show_placeholder_for_recipient=False,
|
||||
show_id=False
|
||||
) %}
|
||||
{% if recipient is not none %}
|
||||
<p class="sms-message-recipient">
|
||||
To:
|
||||
{% if show_placeholder_for_recipient %}
|
||||
<span class="placeholder-no-brackets">
|
||||
phone number
|
||||
</span>
|
||||
{% else %}
|
||||
{{ recipient }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<div class="sms-message-wrapper{% if input_name %}-with-radio{% endif %}">
|
||||
{% if from %}
|
||||
<span class="sms-message-from">
|
||||
{{ from }}
|
||||
</span>
|
||||
{% endif %}
|
||||
{{ body|nl2br }}
|
||||
</div>
|
||||
{% if show_id %}
|
||||
<p class="sms-message-recipient">
|
||||
Template ID: {{ id }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
@@ -1,9 +1,6 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/radios.html" import radio_select %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/letter.html" import letter %}
|
||||
{% from "components/table.html" import list_table, field, text_field, index_field, hidden_field_heading %}
|
||||
{% from "components/file-upload.html" import file_upload %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
@@ -130,28 +127,7 @@
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup if errors else template.replaced_subject,
|
||||
template.formatted_as_markup if errors else template.replaced|safe,
|
||||
from_address='{}@notifications.service.gov.uk'.format(current_service.email_from),
|
||||
from_name=current_service.name,
|
||||
recipient=first_recipient,
|
||||
show_placeholder_for_recipient=errors
|
||||
)}}
|
||||
{% elif 'sms' == template.template_type %}
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup if errors else template.replaced|safe,
|
||||
recipient=first_recipient,
|
||||
show_placeholder_for_recipient=errors
|
||||
)}}
|
||||
</div>
|
||||
</div>
|
||||
{% elif 'letter' == template.template_type %}
|
||||
{{ letter(template.formatted_as_markup if errors else template.replaced|safe) }}
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
|
||||
{% if errors %}
|
||||
{% if request.args.from_test %}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/banner.html" import banner %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/ajax-block.html" import ajax_block %}
|
||||
|
||||
{% block page_title %}
|
||||
@@ -14,20 +12,7 @@
|
||||
{{ uploaded_file_name }}
|
||||
</h1>
|
||||
|
||||
{% if 'sms' == template.template_type %}
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup,
|
||||
)}}
|
||||
</div>
|
||||
</div>
|
||||
{% elif 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup,
|
||||
template.formatted_as_markup
|
||||
)}}
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
|
||||
{{ ajax_block(partials, updates_url, 'status', finished=finished) }}
|
||||
{{ ajax_block(partials, updates_url, 'counts', finished=finished) }}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/api-key.html" import api_key %}
|
||||
|
||||
{% block page_title %}
|
||||
@@ -13,20 +11,7 @@
|
||||
API info
|
||||
</h1>
|
||||
|
||||
{% if 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup,
|
||||
template.formatted_as_markup,
|
||||
) }}
|
||||
{% elif 'sms' == template.template_type %}
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup,
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
|
||||
<div class="bottom-gutter">
|
||||
{{ api_key(template.id, name="Template ID", thing='template ID') }}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/letter.html" import letter %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/file-upload.html" import file_upload %}
|
||||
{% from "components/table.html" import list_table, field, text_field, index_field, index_field_heading %}
|
||||
@@ -22,26 +19,7 @@
|
||||
<h1 class="heading-large">Send yourself a test</h1>
|
||||
{% endif %}
|
||||
|
||||
{% if 'sms' == template.template_type %}
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup,
|
||||
recipient='',
|
||||
show_placeholder_for_recipient=True
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
{% elif 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup,
|
||||
template.formatted_as_markup,
|
||||
recipient='',
|
||||
show_placeholder_for_recipient=True
|
||||
) }}
|
||||
{% elif 'letter' == template.template_type %}
|
||||
{{ letter(template.formatted_as_markup) }}
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
|
||||
<form method="post">
|
||||
{% call(item, row_number) list_table(
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/letter.html" import letter %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/file-upload.html" import file_upload %}
|
||||
{% from "components/table.html" import list_table, text_field, index_field, index_field_heading %}
|
||||
@@ -14,26 +11,7 @@
|
||||
|
||||
<h1 class="heading-large">Upload recipients</h1>
|
||||
|
||||
{% if 'sms' == template.template_type %}
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup,
|
||||
recipient='',
|
||||
show_placeholder_for_recipient=True
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
{% elif 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup,
|
||||
template.formatted_as_markup,
|
||||
recipient='',
|
||||
show_placeholder_for_recipient=True
|
||||
) }}
|
||||
{% elif 'letter' == template.template_type %}
|
||||
{{ letter(template.formatted_as_markup) }}
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
|
||||
<div class="page-footer bottom-gutter">
|
||||
{{file_upload(
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
{% from "components/big-number.html" import big_number %}
|
||||
{% from "components/browse-list.html" import browse_list %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/table.html" import mapping_table, list_table, row, field, text_field, boolean_field, right_aligned_field_heading %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
{% from "components/file-upload.html" import file_upload %}
|
||||
@@ -111,43 +109,6 @@
|
||||
button_text='Sign in', secondary_link='http://example.com', secondary_link_text="I’ve forgotten my password"
|
||||
) }}
|
||||
|
||||
<h2 class="heading-large">SMS message</h2>
|
||||
|
||||
<p>Used to show, preview or choose an SMS template.</p>
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="column-half">
|
||||
{{ sms_message(
|
||||
'Your vehicle tax for LC12 BFL is due on 1 March 2016. Renew online at www.gov.uk/vehicle-tax',
|
||||
) }}
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup
|
||||
) }}
|
||||
{{ sms_message(
|
||||
'Your vehicle tax for LC12 BFL is due on 1 March 2016. Renew online at www.gov.uk/vehicle-tax',
|
||||
'+44 7700 900 306'
|
||||
) }}
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="heading-large">Email message</h2>
|
||||
|
||||
<p>Used to show, preview or choose an email template.</p>
|
||||
|
||||
<div class="grid-row">
|
||||
<div class="column-two-thirds">
|
||||
{{ email_message(
|
||||
subject="Vehicle tax reminder",
|
||||
body="Dear Alice Smith,\n\nYour vehicle tax for LC12 BFL is due on 1 March 2016.\n\nRenew online at www.gov.uk/vehicle-tax",
|
||||
from_name="Vehicle tax",
|
||||
from_address="vehicle.tax@notifications.service.gov.uk"
|
||||
) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="heading-large">Tables</h2>
|
||||
<div class="grid-row">
|
||||
<div class="column-three-quarters">
|
||||
|
||||
@@ -1,23 +1,5 @@
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/letter.html" import letter %}
|
||||
|
||||
<div class="column-two-thirds">
|
||||
{% if 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup,
|
||||
template.formatted_as_markup,
|
||||
id=template.id,
|
||||
expanded=expanded
|
||||
) }}
|
||||
{% elif 'sms' == template.template_type %}
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup,
|
||||
id=template.id
|
||||
) }}
|
||||
{% elif 'letter' == template.template_type %}
|
||||
{{ letter(template.formatted_as_markup) }}
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
</div>
|
||||
<div class="column-one-third">
|
||||
{% if template._template.archived %}
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
|
||||
<div class="column-whole">
|
||||
<h2 class="message-name">{{ template.name }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="column-two-thirds">
|
||||
{% if 'email' == template.template_type %}
|
||||
{{ email_message(
|
||||
template.formatted_subject_as_markup,
|
||||
template.formatted_as_markup,
|
||||
) }}
|
||||
{% elif 'sms' == template.template_type %}
|
||||
{{ sms_message(
|
||||
template.formatted_as_markup
|
||||
) }}
|
||||
{% endif %}
|
||||
{{ template.rendered }}
|
||||
</div>
|
||||
|
||||
<div class="column-one-third">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
|
||||
{% block page_title %}
|
||||
{{ template.name }} – GOV.UK Notify
|
||||
Previous versions – GOV.UK Notify
|
||||
{% endblock %}
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/email-message.html" import email_message %}
|
||||
{% from "components/sms-message.html" import sms_message %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
|
||||
|
||||
19
app/utils.py
19
app/utils.py
@@ -8,6 +8,8 @@ import unicodedata
|
||||
from flask import (abort, current_app, session, request, redirect, url_for)
|
||||
from flask_login import current_user
|
||||
|
||||
from notifications_utils.renderers import SMSPreview, EmailPreview, LetterPreview
|
||||
|
||||
import pyexcel
|
||||
import pyexcel.ext.io
|
||||
import pyexcel.ext.xls
|
||||
@@ -216,3 +218,20 @@ def is_gov_user(email_address):
|
||||
valid_domains = current_app.config['EMAIL_DOMAIN_REGEXES']
|
||||
email_regex = (r"[\.|@]({})$".format("|".join(valid_domains)))
|
||||
return bool(re.search(email_regex, email_address.lower()))
|
||||
|
||||
|
||||
def get_renderer(template_type, service, show_recipient, expand_emails=False):
|
||||
return {
|
||||
'email': EmailPreview(
|
||||
from_name=service['name'],
|
||||
from_address='{}@notifications.service.gov.uk'.format(service['email_from']),
|
||||
expanded=expand_emails,
|
||||
show_recipient=show_recipient
|
||||
),
|
||||
'sms': SMSPreview(
|
||||
prefix=service['name'],
|
||||
sender=service['sms_sender'],
|
||||
show_recipient=show_recipient
|
||||
),
|
||||
'letter': LetterPreview(),
|
||||
}[template_type]
|
||||
|
||||
@@ -18,4 +18,4 @@ pytz==2016.4
|
||||
|
||||
git+https://github.com/alphagov/notifications-python-client.git@3.0.1#egg=notifications-python-client==3.0.1
|
||||
|
||||
git+https://github.com/alphagov/notifications-utils.git@10.3.1#egg=notifications-utils==10.3.1
|
||||
git+https://github.com/alphagov/notifications-utils.git@11.0.2#egg=notifications-utils==11.0.2
|
||||
|
||||
Reference in New Issue
Block a user