diff --git a/README.md b/README.md
index a55cce639..91109d3cd 100644
--- a/README.md
+++ b/README.md
@@ -28,17 +28,17 @@ Node's package management tool.
brew install node
```
-n is a tool for managing different versions of node. The following installs n and uses the latest version of node.
-
+n is a tool for managing different versions of node. The following installs n
+and uses the latest version of node.
+```shell
npm install -g n
n latest
npm rebuild node-sass
+```
-Most of the frontend dependencies are managed using Git Submodules. Some are
-managed with NPM and Bower. To install or update *all the things*, run
+The frontend dependencies are managed using NPM and Bower. To install or update
+*all the things*, run
```shell
- git submodule init
- git submodule update
npm install
npm run build
```
diff --git a/app/__init__.py b/app/__init__.py
index ee5ff453a..8b92019d4 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -1,7 +1,7 @@
import os
import re
-from flask import Flask, session, Markup, render_template
+from flask import Flask, session, Markup, escape, render_template
from flask._compat import string_types
from flask.ext.sqlalchemy import SQLAlchemy
from flask_login import LoginManager
@@ -47,6 +47,7 @@ def create_app(config_name, config_overrides=None):
application.add_template_filter(placeholders)
application.add_template_filter(replace_placeholders)
+ application.add_template_filter(nl2br)
application.after_request(useful_headers_after_request)
register_errorhandlers(application)
@@ -108,6 +109,14 @@ def placeholders(value):
))
+def nl2br(value):
+ _paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')
+
+ result = u'\n\n'.join(u'
%s
' % p.replace('\n', Markup(' \n'))
+ for p in _paragraph_re.split(escape(value)))
+ return Markup(result)
+
+
def replace_placeholders(template, values):
if not template:
return template
diff --git a/app/assets/govuk_elements b/app/assets/govuk_elements
deleted file mode 160000
index 9e44a8d74..000000000
--- a/app/assets/govuk_elements
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 9e44a8d74cbbab9d32fd006bfba05814c8b0dc83
diff --git a/app/assets/govuk_frontend_toolkit b/app/assets/govuk_frontend_toolkit
deleted file mode 160000
index 26b6a60d0..000000000
--- a/app/assets/govuk_frontend_toolkit
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 26b6a60d076c0e717ee4316c21df8938acbf42ff
diff --git a/app/assets/javascripts/apiKey.js b/app/assets/javascripts/apiKey.js
new file mode 100644
index 000000000..30d87278d
--- /dev/null
+++ b/app/assets/javascripts/apiKey.js
@@ -0,0 +1,58 @@
+(function(Modules) {
+ "use strict";
+
+ Modules.ApiKey = function() {
+
+ const states = {
+ 'initial': `
+
+ `,
+ 'keyVisibleBasic': key => `
+ ${key}
+ `,
+ 'keyVisible': key => `
+ ${key}
+
+ `,
+ 'keyCopied': `
+ Copied to clipboard
+
+ `
+ };
+
+ this.copyKey = function(keyElement, callback) {
+ var selection = window.getSelection ? window.getSelection() : document.selection,
+ range = document.createRange();
+ selection.removeAllRanges();
+ range.selectNodeContents(keyElement);
+ selection.addRange(range);
+ document.execCommand('copy');
+ selection.removeAllRanges();
+ callback();
+ };
+
+ this.start = function(component) {
+
+ const $component = $(component).html(states.initial).attr('aria-live', 'polite'),
+ key = $component.data('key');
+
+ $component
+ .on(
+ 'click', '.api-key-button-show', () =>
+ $component.html(
+ document.queryCommandSupported('copy') ?
+ states.keyVisible(key) : states.keyVisibleBasic(key)
+ )
+ )
+ .on(
+ 'click', '.api-key-button-copy', () =>
+ this.copyKey(
+ $('.api-key-key', component)[0], () =>
+ $component.html(states.keyCopied)
+ )
+ );
+
+ };
+ };
+
+})(window.GOVUK.Modules);
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 624984dc0..1a8d54926 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -1 +1,3 @@
$(() => GOVUK.modules.start());
+
+$(() => new GOVUK.SelectionButtons('.block-label input'));
diff --git a/app/assets/stylesheets/_grids.scss b/app/assets/stylesheets/_grids.scss
index f210f4693..e349e22bb 100644
--- a/app/assets/stylesheets/_grids.scss
+++ b/app/assets/stylesheets/_grids.scss
@@ -5,3 +5,7 @@
.column-three-quarters {
@include grid-column(3/4);
}
+
+.bottom-gutter {
+ margin-bottom: $gutter;
+}
diff --git a/app/assets/stylesheets/components/api-key.scss b/app/assets/stylesheets/components/api-key.scss
new file mode 100644
index 000000000..22c787355
--- /dev/null
+++ b/app/assets/stylesheets/components/api-key.scss
@@ -0,0 +1,17 @@
+.api-key {
+
+ &-key {
+ font-family: monospace;
+ display: block;
+ margin-bottom: 10px;
+ }
+
+ &-button-show {
+ @include button($grey-3);
+ }
+
+ &-button-copy {
+ @include button($grey-3);
+ }
+
+}
diff --git a/app/assets/stylesheets/components/banner.scss b/app/assets/stylesheets/components/banner.scss
index 70555d2d1..0e709f9b1 100644
--- a/app/assets/stylesheets/components/banner.scss
+++ b/app/assets/stylesheets/components/banner.scss
@@ -27,3 +27,20 @@
}
}
+
+.banner-dangerous {
+
+ @extend .banner;
+ background: $white;
+ color: $error-colour;
+ border: 5px solid $error-colour;
+ margin: 15px 0;
+ @include bold-19;
+ text-align: left;
+
+ .button {
+ @include button($error-colour);
+ margin-top: 10px;
+ }
+
+}
diff --git a/app/assets/stylesheets/components/email-message.scss b/app/assets/stylesheets/components/email-message.scss
new file mode 100644
index 000000000..c351e4263
--- /dev/null
+++ b/app/assets/stylesheets/components/email-message.scss
@@ -0,0 +1,24 @@
+.email-message {
+
+ margin-bottom: $gutter;
+ border: 1px solid $border-colour;
+
+ &-subject {
+ border-bottom: 1px solid $border-colour;;
+ padding: 10px;
+ @include bold-19;
+ }
+
+ &-body {
+ border-bottom: 1px solid white;
+ padding: 10px;
+ overflow: hidden;
+ max-height: 103px;
+ }
+
+ &-name {
+ @include bold-19;
+ margin: 50px 0 10px 0;
+ }
+
+}
diff --git a/app/assets/stylesheets/components/page-footer.scss b/app/assets/stylesheets/components/page-footer.scss
index 53a94f75b..9b8b2feb1 100644
--- a/app/assets/stylesheets/components/page-footer.scss
+++ b/app/assets/stylesheets/components/page-footer.scss
@@ -7,6 +7,26 @@
margin-top: $gutter;
}
+ &-delete-link {
+
+ line-height: 40px;
+ padding: 0 0 0 5px;
+
+ a:visited,
+ a:link {
+ color: $error-colour;
+ display: inline-block;
+ vertical-align: center;
+ }
+
+ a:hover,
+ a:active {
+ color: $mellow-red;
+ }
+
+ }
+
+
.button {}
.button-destructive {
diff --git a/app/assets/stylesheets/components/sms-message.scss b/app/assets/stylesheets/components/sms-message.scss
index abdd5f9bf..a429edbaa 100644
--- a/app/assets/stylesheets/components/sms-message.scss
+++ b/app/assets/stylesheets/components/sms-message.scss
@@ -45,4 +45,9 @@
margin: -$gutter-half 0 $gutter 0;
}
+ &-name {
+ @include bold-19;
+ margin: 50px 0 10px 0;
+ }
+
}
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index 7343f9348..59b450ec7 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -1,33 +1,33 @@
// Dependencies from GOV.UK Frontend Toolkit
// https://github.com/alphagov/govuk_frontend_toolkit/
-@import '../govuk_frontend_toolkit/stylesheets/conditionals';
-@import '../govuk_frontend_toolkit/stylesheets/shims';
-@import '../govuk_frontend_toolkit/stylesheets/measurements';
-@import '../govuk_frontend_toolkit/stylesheets/css3';
-@import '../govuk_frontend_toolkit/stylesheets/colours';
-@import '../govuk_frontend_toolkit/stylesheets/typography';
-@import '../govuk_frontend_toolkit/stylesheets/grid_layout';
-@import '../govuk_frontend_toolkit/stylesheets/helpers';
-@import '../govuk_frontend_toolkit/stylesheets/url-helpers';
-@import '../govuk_frontend_toolkit/stylesheets/design-patterns/buttons';
-@import '../govuk_frontend_toolkit/stylesheets/design-patterns/alpha-beta';
+@import 'conditionals';
+@import 'shims';
+@import 'measurements';
+@import 'css3';
+@import 'colours';
+@import 'typography';
+@import 'grid_layout';
+@import 'helpers';
+@import 'url-helpers';
+@import 'design-patterns/buttons';
+@import 'design-patterns/alpha-beta';
// Dependencies from GOV.UK Elements
// https://github.com/alphagov/govuk_elements
-@import '../govuk_elements/public/sass/elements/helpers';
-@import '../govuk_elements/public/sass/elements/reset';
-@import '../govuk_elements/public/sass/elements/buttons';
-@import '../govuk_elements/public/sass/elements/details';
-@import '../govuk_elements/public/sass/elements/elements-typography';
-@import '../govuk_elements/public/sass/elements/forms';
-@import '../govuk_elements/public/sass/elements/forms/form-validation';
-@import '../govuk_elements/public/sass/elements/forms/form-block-labels';
-@import '../govuk_elements/public/sass/elements/forms/form-validation';
-@import '../govuk_elements/public/sass/elements/icons';
-@import '../govuk_elements/public/sass/elements/layout';
-@import '../govuk_elements/public/sass/elements/lists';
-@import '../govuk_elements/public/sass/elements/panels';
-@import '../govuk_elements/public/sass/elements/tables';
+@import 'elements/helpers';
+@import 'elements/reset';
+@import 'elements/buttons';
+@import 'elements/details';
+@import 'elements/elements-typography';
+@import 'elements/forms';
+@import 'elements/forms/form-validation';
+@import 'elements/forms/form-block-labels';
+@import 'elements/forms/form-validation';
+@import 'elements/icons';
+@import 'elements/layout';
+@import 'elements/lists';
+@import 'elements/panels';
+@import 'elements/tables';
// Specific to this application
@@ -44,6 +44,8 @@
@import 'components/browse-list';
@import 'components/management-navigation';
@import 'components/dropdown';
+@import 'components/email-message';
+@import 'components/api-key';
@import 'views/job';
diff --git a/app/main/__init__.py b/app/main/__init__.py
index ff64f5c69..7ce30ff8a 100644
--- a/app/main/__init__.py
+++ b/app/main/__init__.py
@@ -5,5 +5,5 @@ main = Blueprint('main', __name__)
from app.main.views import (
index, sign_in, sign_out, register, two_factor, verify, sms, add_service,
code_not_received, jobs, dashboard, templates, service_settings, forgot_password,
- new_password, styleguide, user_profile, choose_service
+ new_password, styleguide, user_profile, choose_service, api_keys
)
diff --git a/app/main/forms.py b/app/main/forms.py
index 2a5a62dcf..11b201402 100644
--- a/app/main/forms.py
+++ b/app/main/forms.py
@@ -166,8 +166,12 @@ class AddServiceForm(Form):
self._names_func = names_func
super(AddServiceForm, self).__init__(*args, **kwargs)
- name = StringField('Service Name', validators=[
- DataRequired(message='Service name can not be empty')])
+ name = StringField(
+ 'Service name',
+ validators=[
+ DataRequired(message='Service name can not be empty')
+ ]
+ )
def validate_name(self, a):
if a.data in self._names_func():
diff --git a/app/main/uploader.py b/app/main/uploader.py
index bedf4ba6d..a1e88e216 100644
--- a/app/main/uploader.py
+++ b/app/main/uploader.py
@@ -1,15 +1,22 @@
-import os
import uuid
from boto3 import resource
-# TODO add service name to bucket name as well
-def s3upload(filepath):
- filename = filepath.split(os.path.sep)[-1]
+def s3upload(service_id, filedata):
upload_id = str(uuid.uuid4())
s3 = resource('s3')
- s3.create_bucket(Bucket=upload_id)
- key = s3.Object(upload_id, filename)
- key.put(Body=open(filepath, 'rb'), ServerSideEncryption='AES256')
+ bucket_name = 'service-{}-notify'.format(service_id)
+ s3.create_bucket(Bucket=bucket_name)
+ contents = '\n'.join(filedata['data'])
+ key = s3.Object(bucket_name, upload_id)
+ key.put(Body=contents, ServerSideEncryption='AES256')
return upload_id
+
+
+def s3download(service_id, upload_id):
+ s3 = resource('s3')
+ bucket_name = 'service-{}-notify'.format(service_id)
+ key = s3.Object(bucket_name, upload_id)
+ contents = key.get()['Body'].read().decode('utf-8')
+ return contents
diff --git a/app/main/views/_templates.py b/app/main/views/_templates.py
new file mode 100644
index 000000000..da7f97c32
--- /dev/null
+++ b/app/main/views/_templates.py
@@ -0,0 +1,39 @@
+templates = [
+ {
+ 'type': 'sms',
+ 'name': 'Confirmation',
+ 'body': 'Lasting power of attorney: We’ve received your application. Applications take between 8 and 10 weeks to process.' # noqa
+ },
+ {
+ 'type': 'sms',
+ 'name': 'Reminder',
+ 'body': 'Vehicle tax: Your vehicle tax for ((registration number)) expires on ((date)). Tax your vehicle at www.gov.uk/vehicle-tax' # noqa
+ },
+ {
+ 'type': 'sms',
+ 'name': 'Warning',
+ 'body': 'Vehicle tax: Your vehicle tax for ((registration number)) has expired. Tax your vehicle at www.gov.uk/vehicle-tax' # noqa
+ },
+ {
+ 'type': 'email',
+ 'name': 'Application alert 06/2016',
+ 'subject': 'Your lasting power of attorney application',
+ 'body': """Dear ((name)),
+
+When you’ve made your lasting power of attorney (LPA), you need to register it \
+with the Office of the Public Guardian (OPG).
+
+You can apply to register your LPA yourself if you’re able to make your own decisions.
+
+Your attorney can also register it for you. You’ll be told if they do and you can \
+object to the registration.
+
+It takes between 8 and 10 weeks to register an LPA if there are no mistakes in the application.
+ """
+ },
+ {
+ 'type': 'sms',
+ 'name': 'Air quality alert',
+ 'body': 'Air pollution levels will be ((level)) in ((region)) tomorrow.'
+ },
+]
diff --git a/app/main/views/add_service.py b/app/main/views/add_service.py
index 4bf3797af..7402ab497 100644
--- a/app/main/views/add_service.py
+++ b/app/main/views/add_service.py
@@ -1,4 +1,4 @@
-from flask import render_template, jsonify, redirect, session, url_for
+from flask import request, render_template, jsonify, redirect, session, url_for, abort
from flask_login import login_required
from app.main import main
from app.main.dao import services_dao, users_dao
@@ -8,11 +8,19 @@ from app.main.forms import AddServiceForm
@main.route("/add-service", methods=['GET', 'POST'])
@login_required
def add_service():
- # TODO fix up this
form = AddServiceForm(services_dao.find_all_service_names)
+ services = services_dao.get_services()
+ if len(services) > 0:
+ heading = 'Set up notifications for your service'
+ else:
+ heading = 'Add a new service'
if form.validate_on_submit():
user = users_dao.get_user_by_id(session['user_id'])
service_id = services_dao.insert_new_service(form.name.data, user)
return redirect(url_for('main.service_dashboard', service_id=service_id))
else:
- return render_template('views/add-service.html', form=form)
+ return render_template(
+ 'views/add-service.html',
+ form=form,
+ heading=heading
+ )
diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py
new file mode 100644
index 000000000..0241346a8
--- /dev/null
+++ b/app/main/views/api_keys.py
@@ -0,0 +1,9 @@
+from flask import render_template
+from flask_login import login_required
+from app.main import main
+
+
+@main.route("/services//api-keys")
+@login_required
+def api_keys(service_id):
+ return render_template('views/api-keys.html', service_id=service_id)
diff --git a/app/main/views/index.py b/app/main/views/index.py
index a41d929c0..c4a543c24 100644
--- a/app/main/views/index.py
+++ b/app/main/views/index.py
@@ -36,9 +36,3 @@ def check_email(service_id):
@login_required
def manage_users(service_id):
return render_template('views/manage-users.html', service_id=service_id)
-
-
-@main.route("/services//api-keys")
-@login_required
-def apikeys(service_id):
- return render_template('views/api-keys.html', service_id=service_id)
diff --git a/app/main/views/sms.py b/app/main/views/sms.py
index 7576eae32..9e937bea7 100644
--- a/app/main/views/sms.py
+++ b/app/main/views/sms.py
@@ -20,24 +20,15 @@ from werkzeug import secure_filename
from app.main import main
from app.main.forms import CsvUploadForm
-from app.main.uploader import s3upload
+from app.main.uploader import (
+ s3upload,
+ s3download
+)
-# TODO move this to the templates directory
-message_templates = [
- {
- 'name': 'Reminder',
- 'body': """
- Vehicle tax: Your vehicle tax for ((registration number)) expires on ((date)).
- Tax your vehicle at www.gov.uk/vehicle-tax
- """
- },
- {
- 'name': 'Warning',
- 'body': """
- Vehicle tax: Your vehicle tax for ((registration number)) has expired.
- Tax your vehicle at www.gov.uk/vehicle-tax
- """
- },
+from ._templates import templates
+
+sms_templates = [
+ template for template in templates if template['type'] == 'sms'
]
@@ -48,68 +39,52 @@ def send_sms(service_id):
if form.validate_on_submit():
try:
csv_file = form.file.data
- filename = _format_filename(csv_file.filename)
- filepath = os.path.join(current_app.config['UPLOAD_FOLDER'],
- filename)
- csv_file.save(filepath)
- _check_file(csv_file.filename, filepath)
+ filedata = _get_filedata(csv_file)
+ upload_id = s3upload(service_id, filedata)
return redirect(url_for('.check_sms',
service_id=service_id,
- recipients=filename))
- except (IOError, ValueError) as e:
+ upload_id=upload_id))
+ except ValueError as e:
message = 'There was a problem uploading: {}'.format(
csv_file.filename)
flash(message)
- if isinstance(e, ValueError):
- flash(str(e))
- os.remove(filepath)
+ flash(str(e))
return redirect(url_for('.send_sms', service_id=service_id))
return render_template('views/send-sms.html',
- message_templates=message_templates,
+ message_templates=sms_templates,
form=form,
service_id=service_id)
-@main.route("/services//sms/check", methods=['GET', 'POST'])
+@main.route("/services//sms/check/",
+ methods=['GET', 'POST'])
@login_required
-def check_sms(service_id):
+def check_sms(service_id, upload_id):
if request.method == 'GET':
- filename = request.args.get('recipients')
- if not filename:
- abort(400)
- filepath = os.path.join(current_app.config['UPLOAD_FOLDER'],
- filename)
- upload_result = _build_upload_result(filepath)
- if upload_result.get('rejects'):
- flash('There was a problem with some of the numbers')
-
+ contents = s3download(service_id, upload_id)
+ upload_result = _get_numbers(contents)
+ # TODO get original file name
return render_template(
'views/check-sms.html',
upload_result=upload_result,
- filename=filename,
- message_template=message_templates[0]['body'],
+ filename='someupload_file_name.csv',
+ message_template=sms_templates[0]['body'],
service_id=service_id
)
elif request.method == 'POST':
- filename = request.form['recipients']
- filepath = os.path.join(current_app.config['UPLOAD_FOLDER'],
- filename)
- try:
- upload_id = s3upload(filepath)
- # TODO when job is created record filename in job itself
- # so downstream pages can get the original filename that way
- session[upload_id] = filename
- return redirect(url_for('main.view_job', service_id=service_id, job_id=upload_id))
- except:
- flash('There as a problem saving the file')
- return redirect(url_for('.check_sms', recipients=filename))
+ # TODO create the job with template, file location etc.
+ return redirect(url_for('main.view_job',
+ service_id=service_id,
+ job_id=upload_id))
-def _check_file(filename, filepath):
- if os.stat(filepath).st_size == 0:
- message = 'The file {} contained no data'.format(filename)
+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)
raise ValueError(message)
+ return {'filename': file.filename, 'data': lines}
def _format_filename(filename):
@@ -119,24 +94,16 @@ def _format_filename(filename):
return secure_filename(formatted_name)
-def _open(file):
- return open(file, 'r')
-
-
-def _build_upload_result(csv_file):
- try:
- file = _open(csv_file, 'r')
- pattern = re.compile(r'^\+44\s?\d{4}\s?\d{6}$')
- reader = csv.DictReader(
- file.read().splitlines(),
- lineterminator='\n',
- quoting=csv.QUOTE_NONE)
- valid, rejects = [], []
- for i, row in enumerate(reader):
- if pattern.match(row['phone']):
- valid.append(row)
- else:
- rejects.append({"line_number": i+2, "phone": row['phone']})
- return {"valid": valid, "rejects": rejects}
- finally:
- file.close()
+def _get_numbers(contents):
+ pattern = re.compile(r'^\+44\s?\d{4}\s?\d{6}$') # need better validation
+ reader = csv.DictReader(
+ contents.split('\n'),
+ lineterminator='\n',
+ quoting=csv.QUOTE_NONE)
+ valid, rejects = [], []
+ for i, row in enumerate(reader):
+ if pattern.match(row['phone']):
+ valid.append(row)
+ else:
+ rejects.append({"line_number": i+2, "phone": row['phone']})
+ return {"valid": valid, "rejects": rejects}
diff --git a/app/main/views/templates.py b/app/main/views/templates.py
index 037e6fd4f..fdba437fe 100644
--- a/app/main/views/templates.py
+++ b/app/main/views/templates.py
@@ -1,16 +1,19 @@
-from flask import request, render_template, redirect, url_for
+from flask import request, render_template, redirect, url_for, flash
from flask_login import login_required
from app.main import main
from app.main.forms import TemplateForm
+from ._templates import templates
+
@main.route("/services//templates")
@login_required
def manage_templates(service_id):
return render_template(
'views/manage-templates.html',
- service_id=service_id
+ service_id=service_id,
+ templates=templates,
)
@@ -31,21 +34,49 @@ def add_template(service_id):
return redirect(url_for('.manage_templates', service_id=service_id))
-@main.route("/services//templates/", methods=['GET', 'POST'])
+@main.route("/services//templates/", methods=['GET', 'POST'])
@login_required
def edit_template(service_id, template_id):
form = TemplateForm()
- form.template_name.data = 'Reminder'
- form.template_body.data = 'Vehicle tax: Your vehicle tax for ((registration number)) expires on ((date)). Tax your vehicle at www.gov.uk/vehicle-tax' # noqa
+ form.template_name.data = templates[template_id - 1]['name']
+ form.template_body.data = templates[template_id - 1]['body']
if request.method == 'GET':
return render_template(
'views/edit-template.html',
h1='Edit template',
form=form,
- service_id=service_id
+ service_id=service_id,
+ template_id=template_id
)
elif request.method == 'POST':
return redirect(url_for('.manage_templates', service_id=service_id))
+
+
+@main.route("/services//templates//delete", methods=['GET', 'POST'])
+@login_required
+def delete_template(service_id, template_id):
+
+ form = TemplateForm()
+
+ form.template_name.data = templates[template_id - 1]['name']
+ form.template_body.data = templates[template_id - 1]['body']
+
+ if request.method == 'GET':
+
+ flash('Are you sure you want to delete ‘{}’?'.format(form.template_name.data), 'delete')
+
+ return render_template(
+ 'views/edit-template.html',
+ h1='Edit template',
+ form=form,
+ service_id=service_id,
+ template_id=template_id
+ )
+ elif request.method == 'POST':
+ if request.form.get('delete'):
+ return redirect(url_for('.manage_templates', service_id=service_id))
+ else:
+ return redirect(url_for('.manage_templates', service_id=service_id))
diff --git a/app/main/views/verify.py b/app/main/views/verify.py
index bb00cfd52..0cdd2607e 100644
--- a/app/main/views/verify.py
+++ b/app/main/views/verify.py
@@ -20,5 +20,5 @@ def verify():
verify_codes_dao.use_code_for_user_and_type(user_id=user.id, code_type='sms')
users_dao.activate_user(user.id)
login_user(user)
- return redirect(url_for('.add_service'))
+ return redirect(url_for('.add_service', first='first'))
return render_template('views/verify.html', form=form)
diff --git a/app/notify_client/sender.py b/app/notify_client/sender.py
index 1b401f1bd..85acc4080 100644
--- a/app/notify_client/sender.py
+++ b/app/notify_client/sender.py
@@ -14,7 +14,6 @@ def send_sms_code(user_id, mobile_number):
verify_codes_dao.add_code(user_id=user_id, code=sms_code, code_type='sms')
notifications_api_client.send_sms(mobile_number=mobile_number,
message=sms_code)
-
return sms_code
diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html
index 43eb174e7..e009a9e60 100644
--- a/app/templates/admin_template.html
+++ b/app/templates/admin_template.html
@@ -56,7 +56,7 @@
Service name
Switch to A N Other service
- Add a new service to Notify…
+ Add a new service to GOV.UK Notify
@@ -68,16 +68,22 @@
{% endif %}
- {% with messages = get_flashed_messages() %}
- {% if messages %}
-
-
- {% for message in messages %}
-
{{ message }}
- {% endfor %}
+ {% with messages = get_flashed_messages(with_categories=true) %}
+ {% if messages %}
+