mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-13 02:18:50 -04:00
Add feature to mark a template as redacted
Works similarly to the delete template flow, because it’s a destructive, one-way action. Not on the edit template page, because it’s not something you want to be considering every time you’re editing a template. And we saw that people couldn’t find the delete button when it was on this page. Adds a bit more CSS for the `dangerous` banner type, because the content here is quite complicated. Breaking it into a list helps, but the spacing didn’t look right, so needed some tweaking. Can ship independently of the code that shows the redaction, but needs the API first.
This commit is contained in:
@@ -252,3 +252,7 @@ details .arrow {
|
||||
color: $secondary-text-colour;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.heading-inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,10 @@
|
||||
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.banner-tour {
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
}
|
||||
|
||||
&-delete-link-without-button {
|
||||
@include core-19;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -383,6 +383,44 @@ def delete_service_template(service_id, template_id):
|
||||
)
|
||||
|
||||
|
||||
@main.route("/services/<service_id>/templates/<template_id>/redact", methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@user_has_permissions('manage_templates', admin_override=True)
|
||||
def redact_template(service_id, template_id):
|
||||
|
||||
if request.method == 'POST':
|
||||
|
||||
service_api_client.redact_service_template(service_id, template_id)
|
||||
|
||||
flash(
|
||||
'Personalised content will be hidden for messages sent with this template',
|
||||
'default_with_tick'
|
||||
)
|
||||
|
||||
return redirect(url_for(
|
||||
'.view_template',
|
||||
service_id=service_id,
|
||||
template_id=template_id,
|
||||
))
|
||||
|
||||
return render_template(
|
||||
'views/templates/template.html',
|
||||
template=get_template(
|
||||
service_api_client.get_service_template(service_id, template_id)['data'],
|
||||
current_service,
|
||||
expand_emails=True,
|
||||
letter_preview_url=url_for(
|
||||
'.view_letter_template_preview',
|
||||
service_id=service_id,
|
||||
template_id=template_id,
|
||||
filetype='png',
|
||||
),
|
||||
show_recipient=True,
|
||||
),
|
||||
show_redaction_message=True,
|
||||
)
|
||||
|
||||
|
||||
@main.route('/services/<service_id>/templates/<template_id>/versions')
|
||||
@login_required
|
||||
@user_has_permissions(
|
||||
|
||||
@@ -168,6 +168,12 @@ class ServiceAPIClient(NotifyAdminAPIClient):
|
||||
endpoint = "/service/{0}/template/{1}".format(service_id, id_)
|
||||
return self.post(endpoint, data)
|
||||
|
||||
def redact_service_template(self, service_id, id_):
|
||||
return self.post(
|
||||
"/service/{}/template/{}".format(service_id, id_),
|
||||
{'redact_personalisation': True}
|
||||
)
|
||||
|
||||
def get_service_template(self, service_id, template_id, version=None, *params):
|
||||
"""
|
||||
Retrieve a service template.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% extends "withnav_template.html" %}
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
{% from "components/page-footer.html" import page_footer %}
|
||||
{% from "components/textbox.html" import textbox %}
|
||||
{% from "components/api-key.html" import api_key %}
|
||||
@@ -9,6 +10,24 @@
|
||||
|
||||
{% block maincolumn_content %}
|
||||
|
||||
{% if show_redaction_message %}
|
||||
<div class="bottom-gutter">
|
||||
{% call banner_wrapper(type='dangerous', subhead='Are you sure you want to hide personalisation after sending?') %}
|
||||
<ul class="list list-bullet">
|
||||
<li>
|
||||
You won’t be able to see personalised content in Notify for this template
|
||||
</li>
|
||||
<li>
|
||||
You can’t undo this
|
||||
</li>
|
||||
</ul>
|
||||
<form method='post'>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
||||
<input type="submit" class="button" name="delete" value="Confirm" />
|
||||
</form>
|
||||
{% endcall %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h1 class="heading-large">{{ template.name }}</h1>
|
||||
|
||||
@@ -18,26 +37,29 @@
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<div class="bottom-gutter">
|
||||
<div class="bottom-gutter-1-2">
|
||||
{{ api_key(template.id, name="Template ID", thing='template ID') }}
|
||||
</div>
|
||||
|
||||
{% if template._template.updated_at %}
|
||||
<div class="bottom-gutter-1-2">
|
||||
<h2 class="heading-small">Last edited {{ template._template.updated_at|format_delta }}</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 %}
|
||||
|
||||
{% if current_user.has_permissions(permissions=['manage_templates'], admin_override=True) %}
|
||||
<div class="bottom-gutter">
|
||||
{{ page_footer(
|
||||
delete_link=url_for('.delete_service_template', service_id=current_service.id, template_id=template.id),
|
||||
delete_link_text='Delete this template'
|
||||
) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="bottom-gutter-1-2">
|
||||
{% if template._template.updated_at %}
|
||||
<h2 class="heading-small bottom-gutter-2-3 heading-inline">Last edited {{ template._template.updated_at|format_delta }}</h2>
|
||||
 
|
||||
<a href="{{ url_for('.view_template_versions', service_id=current_service.id, template_id=template.id) }}">See previous versions</a>
|
||||
 
|
||||
<br/>
|
||||
{% endif %}
|
||||
{% if current_user.has_permissions(permissions=['manage_templates'], admin_override=True) %}
|
||||
<span class="page-footer-delete-link page-footer-delete-link-without-button">
|
||||
<a href="{{ url_for('.delete_service_template', service_id=current_service.id, template_id=template.id) }}">Delete this template</a>
|
||||
</span>
|
||||
 
|
||||
{% if not template.redact_personalisation %}
|
||||
<span class="page-footer-delete-link page-footer-delete-link-without-button">
|
||||
<a href="{{ url_for('.redact_template', service_id=current_service.id, template_id=template.id) }}">Hide personalisation after sending</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -942,3 +942,48 @@ def test_should_create_sms_template_without_downgrading_unicode_characters(
|
||||
ANY # process_type
|
||||
)
|
||||
assert resp.status_code == 302
|
||||
|
||||
|
||||
def test_should_show_message_before_redacting_template(
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
service_one,
|
||||
fake_uuid,
|
||||
):
|
||||
|
||||
page = client_request.get(
|
||||
'main.redact_template',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
)
|
||||
|
||||
assert (
|
||||
'Are you sure you want to hide personalisation after sending?'
|
||||
) in page.select('.banner-dangerous')[0].text
|
||||
|
||||
form = page.select('.banner-dangerous form')[0]
|
||||
|
||||
assert 'action' not in form
|
||||
assert form['method'] == 'post'
|
||||
|
||||
|
||||
def test_should_show_redact_template(
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
mock_redact_template,
|
||||
service_one,
|
||||
fake_uuid,
|
||||
):
|
||||
|
||||
page = client_request.post(
|
||||
'main.redact_template',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_follow_redirects=True,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select('.banner-default-with-tick')[0].text) == (
|
||||
'Personalised content will be hidden for messages sent with this template'
|
||||
)
|
||||
|
||||
mock_redact_template.assert_called_once_with(SERVICE_ONE_ID, fake_uuid)
|
||||
|
||||
@@ -518,6 +518,11 @@ def mock_delete_service_template(mocker):
|
||||
'app.service_api_client.delete_service_template', side_effect=_delete)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_redact_template(mocker):
|
||||
return mocker.patch('app.service_api_client.redact_service_template')
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def api_user_pending(fake_uuid):
|
||||
from app.notify_client.user_api_client import User
|
||||
|
||||
Reference in New Issue
Block a user