diff --git a/app/__init__.py b/app/__init__.py index 558c82252..45a08188a 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -15,6 +15,8 @@ from app.notify_client.api_key_api_client import ApiKeyApiClient from app.notify_client.user_api_client import UserApiClient from app.notify_client.job_api_client import JobApiClient from app.notify_client.status_api_client import StatusApiClient +from app.notify_client.permission_api_client import PermissionApiClient +from app.notify_client.invite_api_client import InviteApiClient from app.its_dangerous_session import ItsdangerousSessionInterface from app.asset_fingerprinter import AssetFingerprinter from app.utils import validate_phone_number, InvalidPhoneError @@ -30,7 +32,9 @@ user_api_client = UserApiClient() api_key_api_client = ApiKeyApiClient() job_api_client = JobApiClient() status_api_client = StatusApiClient() +invite_api_client = InviteApiClient() asset_fingerprinter = AssetFingerprinter() +permission_api_client = PermissionApiClient() def create_app(config_name, config_overrides=None): @@ -47,6 +51,8 @@ def create_app(config_name, config_overrides=None): api_key_api_client.init_app(application) job_api_client.init_app(application) status_api_client.init_app(application) + permission_api_client.init_app(application) + invite_api_client.init_app(application) login_manager.init_app(application) login_manager.login_view = 'main.sign_in' diff --git a/app/assets/stylesheets/_grids.scss b/app/assets/stylesheets/_grids.scss index 7f8eb724f..5e8643173 100644 --- a/app/assets/stylesheets/_grids.scss +++ b/app/assets/stylesheets/_grids.scss @@ -15,3 +15,7 @@ margin-bottom: $gutter; clear: both; } + +.bottom-gutter-2-3 { + margin-bottom: $gutter * 2/3; +} diff --git a/app/main/forms.py b/app/main/forms.py index a2885fe8f..7bb000cc7 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -164,13 +164,13 @@ class AddServiceForm(Form): name = StringField( 'Service name', validators=[ - DataRequired(message='Service name can not be empty') + DataRequired(message='Service name can’t be empty') ] ) def validate_name(self, a): if a.data in self._names_func(): - raise ValidationError('Service name already exists') + raise ValidationError('This service name is already in use') class ServiceNameForm(Form): diff --git a/app/main/views/add_service.py b/app/main/views/add_service.py index ad5d8f715..9cee69b8a 100644 --- a/app/main/views/add_service.py +++ b/app/main/views/add_service.py @@ -11,39 +11,15 @@ from app.main.forms import AddServiceForm @login_required def add_service(): form = AddServiceForm(services_dao.find_all_service_names) - services = services_dao.get_services(current_user.id) - if len(services['data']) == 0: - heading = 'Which service do you want to set up notifications for?' - else: - heading = 'Add a new service' + heading = 'Which service do you want to set up notifications for?' if form.validate_on_submit(): session['service_name'] = form.name.data - return redirect(url_for('main.add_from_address')) + user = users_dao.get_user_by_id(session['user_id']) + service_id = services_dao.insert_new_service(session['service_name'], user.id) + return redirect(url_for('main.service_dashboard', service_id=service_id)) else: return render_template( 'views/add-service.html', form=form, heading=heading ) - - -@main.route("/confirm-add-service", methods=['GET', 'POST']) -@login_required -def add_from_address(): - if request.method == 'POST': - user = users_dao.get_user_by_id(session['user_id']) - service_id = services_dao.insert_new_service(session['service_name'], user.id) - return redirect(url_for('main.service_dashboard', service_id=service_id)) - else: - return render_template( - 'views/add-from-address.html', - service_name=session['service_name'], - from_address="{}@notifications.service.gov.uk".format(_email_safe(session['service_name'])) - ) - - -def _email_safe(string): - return "".join([ - character.lower() if character.isalnum() or character == "." else "" - for character in re.sub("\s+", ".", string.strip()) - ]) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index 36959a86d..8053e2cf9 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -3,6 +3,7 @@ from flask_login import login_required from app.main import main from app.main.forms import CreateKeyForm from app import api_key_api_client +from app.utils import user_has_permissions @main.route("/services//documentation") @@ -13,6 +14,7 @@ def documentation(service_id): @main.route("/services//api-keys") @login_required +@user_has_permissions('manage_api_keys') def api_keys(service_id): return render_template( 'views/api-keys.html', @@ -23,6 +25,7 @@ def api_keys(service_id): @main.route("/services//api-keys/create", methods=['GET', 'POST']) @login_required +@user_has_permissions('manage_api_keys') def create_api_key(service_id): key_names = [ key['name'] for key in api_key_api_client.get_api_keys(service_id=service_id)['apiKeys'] @@ -41,6 +44,7 @@ def create_api_key(service_id): @main.route("/services//api-keys/revoke/", methods=['GET', 'POST']) @login_required +@user_has_permissions('manage_api_keys') def revoke_api_key(service_id, key_id): key_name = api_key_api_client.get_api_keys(service_id=service_id, key_id=key_id)['apiKeys'][0]['name'] if request.method == 'GET': diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py index cb15fce90..9f7dc1044 100644 --- a/app/main/views/dashboard.py +++ b/app/main/views/dashboard.py @@ -23,6 +23,7 @@ def service_dashboard(service_id): try: service = get_service_by_id(service_id) session['service_name'] = service['data']['name'] + session['service_id'] = service['data']['id'] except HTTPError as e: if e.status_code == 404: abort(404) diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py index 96d97191e..b320699b4 100644 --- a/app/main/views/jobs.py +++ b/app/main/views/jobs.py @@ -13,6 +13,7 @@ from notification_utils.template import Template from app import job_api_client from app.main import main from app.main.dao import templates_dao +from app.main.dao import services_dao now = time.strftime('%H:%M') @@ -37,6 +38,7 @@ def view_jobs(service_id): @main.route("/services//jobs/") @login_required def view_job(service_id, job_id): + service = services_dao.get_service_by_id_or_404(service_id) try: job = job_api_client.get_job(service_id, job_id)['data'] messages = [] @@ -56,9 +58,11 @@ def view_job(service_id, job_id): uploaded_file_name=job['original_file_name'], uploaded_file_time=job['created_at'], template=Template( - templates_dao.get_service_template_or_404(service_id, job['template'])['data'] + templates_dao.get_service_template_or_404(service_id, job['template'])['data'], + prefix=service['name'] ), - service_id=service_id + service_id=service_id, + service=service ) except HTTPError as e: if e.status_code == 404: diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 0a9a2d067..0b5f0e7f0 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -7,13 +7,18 @@ from flask import ( flash ) -from flask_login import login_required, current_user +from flask_login import ( + login_required, + current_user +) + +from notifications_python_client.errors import HTTPError from app.main import main -from app.main.dao import users_dao from app.main.forms import InviteUserForm from app.main.dao.services_dao import get_service_by_id_or_404 from app import user_api_client +from app import invite_api_client fake_users = [ { @@ -29,14 +34,19 @@ fake_users = [ @main.route("/services//users") @login_required def manage_users(service_id): - users = user_api_client.get_users_for_service(service_id=service_id) - return render_template( - 'views/manage-users.html', - service_id=service_id, - users=users, - current_user=current_user, - invited_users=[] - ) + try: + users = user_api_client.get_users_for_service(service_id=service_id) + invited_users = invite_api_client.get_invites_for_service(service_id=service_id) + return render_template('views/manage-users.html', + service_id=service_id, + users=users, + current_user=current_user, + invited_users=invited_users) + except HTTPError as e: + if e.status_code == 404: + abort(404) + else: + raise e @main.route("/services//users/invite", methods=['GET', 'POST']) @@ -44,10 +54,19 @@ def manage_users(service_id): def invite_user(service_id): form = InviteUserForm() - if form.validate_on_submit(): - flash('Invite sent to {}'.format(form.email_address.data), 'default_with_tick') - return redirect(url_for('.manage_users', service_id=service_id)) + email_address = form.email_address.data + permissions = _get_permissions(request.form) + try: + resp = invite_api_client.create_invite(current_user.id, service_id, email_address, permissions) + flash('Invite sent to {}'.format(resp['email_address']), 'default_with_tick') + return redirect(url_for('.manage_users', service_id=service_id)) + + except HTTPError as e: + if e.status_code == 404: + abort(404) + else: + raise e return render_template( 'views/invite-user.html', @@ -95,3 +114,14 @@ def delete_user(service_id, user_id): service=get_service_by_id_or_404(service_id), service_id=service_id ) + + +def _get_permissions(form): + permissions = [] + if form.get('send_messages') and form['send_messages'] == 'yes': + permissions.append('send_messages') + if form.get('manage_service') and form['manage_service'] == 'yes': + permissions.append('manage_service') + if form.get('manage_api_keys') and form['manage_api_keys'] == 'yes': + permissions.append('manage_api_keys') + return ','.join(permissions) diff --git a/app/main/views/send.py b/app/main/views/send.py index 91a41fc5f..856403105 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -1,9 +1,6 @@ import csv import io import uuid -import botocore - -from datetime import date from flask import ( request, @@ -17,7 +14,6 @@ from flask import ( ) from flask_login import login_required, current_user -from werkzeug import secure_filename from notifications_python_client.errors import HTTPError from utils.template import Template, NeededByTemplateError, NoPlaceholderForDataError @@ -32,16 +28,23 @@ from app.main.dao import services_dao from app import job_api_client from app.utils import validate_recipient, InvalidPhoneError, InvalidEmailError -first_column_header = { - 'email': 'email', - 'sms': 'phone' +page_headings = { + 'email': 'Send emails', + 'sms': 'Send text messages' } +@main.route("/services//send/letters", methods=['GET']) +def letters_stub(service_id): + return render_template( + 'views/letters.html', service_id=service_id + ) + + @main.route("/services//send/", methods=['GET']) def choose_template(service_id, template_type): - services_dao.get_service_by_id_or_404(service_id) + service = services_dao.get_service_by_id_or_404(service_id) if template_type not in ['email', 'sms']: abort(404) @@ -53,11 +56,17 @@ def choose_template(service_id, template_type): else: raise e return render_template( - 'views/choose-{}-template.html'.format(template_type), + 'views/choose-template.html', templates=[ - Template(template) for template in templates_dao.get_service_templates(service_id)['data'] + Template( + template, + prefix=service['name'] + ) for template in templates_dao.get_service_templates(service_id)['data'] if template['template_type'] == template_type ], + template_type=template_type, + page_heading=page_headings[template_type], + service=service, has_jobs=len(jobs), service_id=service_id ) @@ -70,7 +79,7 @@ def send_messages(service_id, template_id): form = CsvUploadForm() if form.validate_on_submit(): try: - csv_file = form.file.data + csv_file = form.file filedata = _get_filedata(csv_file) upload_id = str(uuid.uuid4()) s3upload(upload_id, service_id, filedata, current_app.config['AWS_REGION']) @@ -79,19 +88,20 @@ def send_messages(service_id, template_id): service_id=service_id, upload_id=upload_id)) except ValueError as e: - flash('There was a problem uploading: {}'.format(csv_file.filename)) + flash('There was a problem uploading: {}'.format(csv_file.data.filename)) flash(str(e)) return redirect(url_for('.send_messages', service_id=service_id, template_id=template_id)) service = services_dao.get_service_by_id_or_404(service_id) template = Template( - templates_dao.get_service_template_or_404(service_id, template_id)['data'] + templates_dao.get_service_template_or_404(service_id, template_id)['data'], + prefix=service['name'] ) return render_template( 'views/send.html', template=template, - column_headers=[first_column_header[template.template_type]] + template.placeholders_as_markup, + column_headers=['to'] + template.placeholders_as_markup, form=form, service=service, service_id=service_id @@ -105,10 +115,14 @@ def get_example_csv(service_id, template_id): placeholders = list(Template(template).placeholders) output = io.StringIO() writer = csv.writer(output) - writer.writerow([first_column_header[template['template_type']]] + placeholders) - writer.writerow([current_user.mobile_number] + ["test {}".format(header) for header in placeholders]) - - return(output.getvalue(), 200, {'Content-Type': 'text/csv; charset=utf-8'}) + writer.writerow(['to'] + placeholders) + writer.writerow([ + { + 'email': current_user.email_address, + 'sms': current_user.mobile_number + }[template['template_type']] + ] + ["test {}".format(header) for header in placeholders]) + return output.getvalue(), 200, {'Content-Type': 'text/csv; charset=utf-8'} @main.route("/services//send//to-self", methods=['GET']) @@ -118,7 +132,7 @@ def send_message_to_self(service_id, template_id): placeholders = list(Template(template).placeholders) output = io.StringIO() writer = csv.writer(output) - writer.writerow([first_column_header[template['template_type']]] + placeholders) + writer.writerow(['to'] + placeholders) writer.writerow([current_user.mobile_number] + ["test {}".format(header) for header in placeholders]) filedata = { 'file_name': 'Test run', @@ -140,29 +154,30 @@ def check_messages(service_id, upload_id): upload_data = session['upload_data'] template_id = upload_data.get('template_id') + service = services_dao.get_service_by_id_or_404(service_id) if request.method == 'GET': contents = s3download(service_id, upload_id) if not contents: flash('There was a problem reading your upload file') raw_template = templates_dao.get_service_template_or_404(service_id, template_id)['data'] - recipient_type = first_column_header[raw_template['template_type']] upload_result = _get_rows(contents, raw_template) session['upload_data']['notification_count'] = len(upload_result['rows']) template = Template( raw_template, values=upload_result['rows'][0] if upload_result['valid'] else {}, - drop_values={recipient_type} + drop_values={'to'}, + prefix=service['name'] ) return render_template( - 'views/check-sms.html', + 'views/check.html', upload_result=upload_result, template=template, - column_headers=[recipient_type] + list( - template.placeholders if upload_result['valid'] else template.placeholders_as_markup - ), + page_heading=page_headings[template.template_type], + column_headers=['to'] + list(template.placeholders_as_markup), original_file_name=upload_data.get('original_file_name'), service_id=service_id, + service=service, form=CsvUploadForm() ) elif request.method == 'POST': @@ -184,17 +199,34 @@ def check_messages(service_id, upload_id): def _get_filedata(file): - lines = file.read().decode('utf-8').splitlines() - if len(lines) < 2: # must be at least header and one line - message = 'The file {} contained no data'.format(file.filename) + import itertools + reader = csv.reader( + file.data.getvalue().decode('utf-8').splitlines(), + quoting=csv.QUOTE_NONE, + skipinitialspace=True + ) + lines = [] + for row in reader: + non_empties = itertools.dropwhile(lambda x: x.strip() == '', row) + has_content = [] + for item in non_empties: + has_content.append(item) + if has_content: + lines.append(row) + + if len(lines) < 2: # must be header row and at least one data row + message = 'The file {} contained no data'.format(file.data.filename) raise ValueError(message) - return {'file_name': file.filename, 'data': lines} + + content_lines = [] + for row in lines: + content_lines.append(','.join(row).rstrip(',')) + return {'file_name': file.data.filename, 'data': content_lines} def _get_rows(contents, raw_template): reader = csv.DictReader( contents.split('\n'), - lineterminator='\n', quoting=csv.QUOTE_NONE, skipinitialspace=True ) @@ -203,12 +235,11 @@ def _get_rows(contents, raw_template): for row in reader: rows.append(row) try: - recipient_column = first_column_header[raw_template['template_type']] validate_recipient( - row[recipient_column], + row.get('to', ''), template_type=raw_template['template_type'] ) - Template(raw_template, values=row, drop_values={recipient_column}).replaced + Template(raw_template, values=row, drop_values={'to'}).replaced except (InvalidEmailError, InvalidPhoneError, NeededByTemplateError, NoPlaceholderForDataError): valid = False return {"valid": valid, "rows": rows} diff --git a/app/notify_client/invite_api_client.py b/app/notify_client/invite_api_client.py new file mode 100644 index 000000000..515422780 --- /dev/null +++ b/app/notify_client/invite_api_client.py @@ -0,0 +1,29 @@ + +from notifications_python_client.base import BaseAPIClient + + +class InviteApiClient(BaseAPIClient): + def __init__(self, base_url=None, client_id=None, secret=None): + super(self.__class__, self).__init__(base_url=base_url or 'base_url', + client_id=client_id or 'client_id', + secret=secret or 'secret') + + def init_app(self, app): + self.base_url = app.config['API_HOST_NAME'] + self.client_id = app.config['ADMIN_CLIENT_USER_NAME'] + self.secret = app.config['ADMIN_CLIENT_SECRET'] + + def create_invite(self, invite_from_id, service_id, email_address, permissions): + data = { + 'service': str(service_id), + 'email_address': email_address, + 'from_user': invite_from_id, + 'permissions': permissions + } + resp = self.post(url='/service/{}/invite'.format(service_id), data=data) + return resp['data'] + + def get_invites_for_service(self, service_id): + endpoint = '/service/{}/invite'.format(service_id) + resp = self.get(endpoint) + return resp['data'] diff --git a/app/notify_client/job_api_client.py b/app/notify_client/job_api_client.py index e39b19a23..b24643c8c 100644 --- a/app/notify_client/job_api_client.py +++ b/app/notify_client/job_api_client.py @@ -1,4 +1,3 @@ -import uuid from notifications_python_client.base import BaseAPIClient @@ -23,7 +22,6 @@ class JobApiClient(BaseAPIClient): def create_job(self, job_id, service_id, template_id, original_file_name, notification_count): data = { "id": job_id, - "service": service_id, "template": template_id, "original_file_name": original_file_name, "bucket_name": "service-{}-notify".format(service_id), diff --git a/app/notify_client/permission_api_client.py b/app/notify_client/permission_api_client.py new file mode 100644 index 000000000..a112251af --- /dev/null +++ b/app/notify_client/permission_api_client.py @@ -0,0 +1,25 @@ +import uuid + +from notifications_python_client.base import BaseAPIClient + + +class PermissionApiClient(BaseAPIClient): + def __init__(self, base_url=None, client_id=None, secret=None): + super(self.__class__, self).__init__(base_url=base_url or 'base_url', + client_id=client_id or 'client_id', + secret=secret or 'secret') + + def init_app(self, app): + self.base_url = app.config['API_HOST_NAME'] + self.client_id = app.config['ADMIN_CLIENT_USER_NAME'] + self.secret = app.config['ADMIN_CLIENT_SECRET'] + + def delete_permission(self, permission_id): + return self.delete(url='/permission/{}'.format(permission_id))['data'] + + def create_permission(self, permission, user_id, service_id): + return self.post( + url='/permission', + data={'permission': permission, + 'user': user_id, + 'service': service_id})['data'] diff --git a/app/notify_client/user_api_client.py b/app/notify_client/user_api_client.py index 3d0e8b1e7..e0d1057d1 100644 --- a/app/notify_client/user_api_client.py +++ b/app/notify_client/user_api_client.py @@ -94,7 +94,7 @@ class User(UserMixin): self._email_address = fields.get('email_address') self._mobile_number = fields.get('mobile_number') self._password_changed_at = fields.get('password_changed_at') - self._permissions = set(fields.get('permissions')) if fields.get('permission') is not None else set() + self._permissions = fields.get('permissions') self._failed_login_count = 0 self._state = fields.get('state') self.max_failed_login_count = max_failed_login_count @@ -165,18 +165,12 @@ class User(UserMixin): @permissions.setter def permissions(self, permissions): - if permissions is None: - permissions = set() - self._permissions = set(permissions) + raise AttributeError("Read only property") - def add_permissions(self, permissions): - self._permissions.update(permissions) - - def remove_permissions(self, permissions): - self._permissions -= permissions - - def has_permissions(self, permissions): - return self._permissions > set(permissions) + def has_permissions(self, service_id, permissions): + if service_id in self._permissions: + return set(self._permissions[service_id]) > set(permissions) + return False @property def failed_login_count(self): diff --git a/app/templates/components/yes-no.html b/app/templates/components/yes-no.html index 4432d6a9f..554a8e1fc 100644 --- a/app/templates/components/yes-no.html +++ b/app/templates/components/yes-no.html @@ -5,11 +5,11 @@
diff --git a/app/templates/main_nav.html b/app/templates/main_nav.html index a08a24a4a..216bec23c 100644 --- a/app/templates/main_nav.html +++ b/app/templates/main_nav.html @@ -2,16 +2,23 @@ + {% if current_user.has_permissions(session.get('service_id', ''), ['send_messages']) %} + {% endif %} + {% if current_user.has_permissions(session.get('service_id', ''), ['manage_service']) %} + {% endif %} + {% if current_user.has_permissions(session.get('service_id', ''), ['manage_api_keys']) %} + {% endif %} diff --git a/app/templates/views/add-from-address.html b/app/templates/views/add-from-address.html deleted file mode 100644 index a67f3c6d3..000000000 --- a/app/templates/views/add-from-address.html +++ /dev/null @@ -1,42 +0,0 @@ -{% extends "withoutnav_template.html" %} -{% from "components/textbox.html" import textbox %} -{% from "components/page-footer.html" import page_footer %} -{% from "components/sms-message.html" import sms_message %} -{% from "components/email-message.html" import email_message %} - -{% block page_title %} - Preview your service name – GOV.UK Notify -{% endblock %} - -{% block maincolumn_content %} - -

- Preview your service name -

- -
-
- {{ sms_message( - "{}: we received your payment, thank you".format(service_name), - name="Text message", - recipient='Sent from 40604' - ) }} -
-
-
-
- {{ email_message( - subject="We received your payment, thank you", - body="Dear Alice Smith,\n\nThank you for…", - from_name=service_name, - from_address=from_address, - name="Email", - ) }} -
-
- -
- {{page_footer('Looks good', back_link=url_for(".add_service"))}} -
- -{% endblock %} diff --git a/app/templates/views/add-service.html b/app/templates/views/add-service.html index f0b4a5ff7..ec03a91e9 100644 --- a/app/templates/views/add-service.html +++ b/app/templates/views/add-service.html @@ -16,16 +16,29 @@

- Be specific. Remember that there might be other people in your - organisation using GOV.UK Notify. + Be specific to your service. Remember that there might be + other people in your organisation using GOV.UK Notify.

+

+ Users will see this: +

+ +
    +
  • + at the start of every text message, eg ‘Vehicle tax: we received your + payment, thank you’ +
  • +
  • + as your email sender name +
  • +
+
{{ textbox(form.name, hint="You can change this later") }} - - {{ page_footer('Continue') }} + {{ page_footer('Add service') }}
diff --git a/app/templates/views/check-email.html b/app/templates/views/check-email.html deleted file mode 100644 index 3ca4830bf..000000000 --- a/app/templates/views/check-email.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "withnav_template.html" %} - -{% block page_title %} - Send email – GOV.UK Notify -{% endblock %} - -{% block maincolumn_content %} - -

Send email

- -

This page will be where we check the email messages we're about to send

- -

- Send email messages -

- - -{% endblock %} diff --git a/app/templates/views/check-sms.html b/app/templates/views/check.html similarity index 69% rename from app/templates/views/check-sms.html rename to app/templates/views/check.html index e0de38dca..315bc32eb 100644 --- a/app/templates/views/check-sms.html +++ b/app/templates/views/check.html @@ -1,4 +1,5 @@ {% extends "withnav_template.html" %} +{% from "components/email-message.html" import email_message %} {% from "components/sms-message.html" import sms_message %} {% from "components/table.html" import list_table, field %} {% from "components/placeholder.html" import placeholder %} @@ -6,7 +7,7 @@ {% from "components/page-footer.html" import page_footer %} {% block page_title %} - Check and confirm – GOV.UK Notify + {{ "Check and confirm" if upload_result.valid else page_heading }} – GOV.UK Notify {% endblock %} {% block maincolumn_content %} @@ -25,18 +26,25 @@ {% endif %}

- {{ "Check and confirm" if upload_result.valid else "Send text messages" }} + {{ "Check and confirm" if upload_result.valid else page_heading }}

-
-
- {% if template.missing_data or template.additional_data %} - {{ sms_message(template.formatted_as_markup)}} - {% else %} - {{ sms_message(template.replaced)}} - {% endif %} + {% if 'email' == template.template_type %} + {{ email_message( + template.subject, + template.replaced if upload_result.valid else template.formatted_as_markup, + from_address='{}@notifications.service.gov.uk'.format(service.email_from), + from_name=service.name + )}} + {% elif 'sms' == template.template_type %} +
+
+ {{ sms_message( + template.replaced if upload_result.valid else template.formatted_as_markup + )}} +
-
+ {% endif %} {% if upload_result.valid %}
@@ -53,13 +61,13 @@ caption=original_file_name, field_headings=column_headers ) %} - {% if item.phone|valid_phone_number %} + {% if item.to or ''|valid_phone_number %} {% call field() %} - {{ item.phone }} + {{ item.to }} {% endcall %} {% else %} {% call field(status='missing') %} - {{ item.phone }} + {{ item.to }} {% endcall %} {% endif %} {% for column in template.placeholders %} diff --git a/app/templates/views/choose-email-template.html b/app/templates/views/choose-email-template.html deleted file mode 100644 index 5452a5da8..000000000 --- a/app/templates/views/choose-email-template.html +++ /dev/null @@ -1,36 +0,0 @@ -{% extends "withnav_template.html" %} -{% from "components/email-message.html" import email_message %} -{% from "components/page-footer.html" import page_footer %} -{% from "components/textbox.html" import textbox %} - -{% block page_title %} - Send emails – GOV.UK Notify -{% endblock %} - -{% block maincolumn_content %} - -

Send emails

- - - - {% if templates %} -
- {% for template in templates %} -
- {{ email_message(template.subject, template.formatted_as_markup, name=template.name) }} -
-
- -
- {% endfor %} -
- {% endif %} - -

- Add a new template -

- -
-{% endblock %} diff --git a/app/templates/views/choose-sms-template.html b/app/templates/views/choose-template.html similarity index 69% rename from app/templates/views/choose-sms-template.html rename to app/templates/views/choose-template.html index 5508ca4fb..7fb87b827 100644 --- a/app/templates/views/choose-sms-template.html +++ b/app/templates/views/choose-template.html @@ -1,15 +1,16 @@ {% 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 %} {% block page_title %} - Send text messages – GOV.UK Notify + {{ page_heading }} – GOV.UK Notify {% endblock %} {% block maincolumn_content %} -

Send text messages

+

{{ page_heading }}

@@ -26,7 +27,15 @@
{% for template in templates %}
- {{ sms_message(template.formatted_as_markup, name=template.name) }} + {% if 'email' == template_type %} + {{ email_message( + template.subject, + template.formatted_as_markup, + name=template.name + ) }} + {% elif 'sms' == template_type %} + {{ sms_message(template.formatted_as_markup, name=template.name) }} + {% endif %}