diff --git a/.travis.yml b/.travis.yml
index b88f96454..f7d0352be 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,8 @@ addons:
postgresql: '9.3'
env:
secure: jT9BIioqBMkOdLZhU+WJNdnRJ+06G7qUx4QqEVldp96dJwmWpPEvA0XbitdnQt/WXYkpMlDbgSApvvGj2ZNvdpowRRe5HFX8D2Udhi2g9+cXgKrQxH6zv0evJyQLOjCINW6KtgMCJ5wkYR3qQ4BQawlDt6ecpmeboKTmvs2W8jZ09aV4IKKvdd7BwFon10QVPF5ny10G83unLtKnKgRMjSSLnaEiA78pE/LSUkekK4mhmtl+yfQf60cIuQGcN9NCYIt5PrdYYyMkbUaht9ykwL2C11sp5JYPClI9k6lrlpGJCdL9wbJwejGhR/pEqwJ4tKK8Zv+mngmkbzE6fd5ehuRMnIUAifG4t3p6WbhKwY5pJsdVyPgWcRSPXOJA7yEcAeTAvWcC++6mCIFBeMxt/yQNw02jkFHeNKRh2twTRvr4xWZHq9FsVxTEVz89OOuue3IkkyDNmVusGJ9+AVRIn9Oa+U/r3bDnrs7jz+meSwb82GZUBzFpUe2pe8qeBE572Ay7yHB73VHUgp/2A1qkZ4SnTjTpMbnS5RdXTgwtMkOs5MLZgteCVxFL3sHcr9e/B3UIUnzKUSPXXOjHyDxBwrABWo81V9Vp2IPV7P9Ofv8zroudjQxK5MOcbmiPQF+eEB9L4DvkUBNsGxtJ/nmPp6tmN0Xjo0xXVdZCEVj29Og=
+before_install:
+- nvm install 5.0.0
install:
- npm install
- pip install -r requirements_for_test.txt
diff --git a/app/assets/javascripts/highlightTags.js b/app/assets/javascripts/highlightTags.js
new file mode 100644
index 000000000..472d479c7
--- /dev/null
+++ b/app/assets/javascripts/highlightTags.js
@@ -0,0 +1,43 @@
+(function(Modules) {
+ "use strict";
+
+ if (
+ !('oninput' in document.createElement('input'))
+ ) return;
+
+ const tagPattern = /\(\([^\)\(]+\)\)/g;
+
+ Modules.HighlightTags = function() {
+
+ this.start = function(textarea) {
+
+ this.$textbox = $(textarea)
+ .wrap(`
+
+ `)
+ .after(this.$backgroundMaskForeground = $(`
+
+
+
+ `))
+ .on("input", this.update)
+ .on("scroll", this.maintainScrollParity);
+
+ this.$textbox
+ .trigger("input");
+
+ };
+
+ this.update = () => this.$backgroundMaskForeground.html(
+ this.$textbox.val().replace(
+ tagPattern, match => `${match}`
+ )
+ );
+
+ this.maintainScrollParity = () => this.$backgroundMaskForeground.scrollTop(
+ this.$textbox.scrollTop()
+ );
+
+ };
+
+})(window.GOVUK.Modules);
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 5f96d14b0..624984dc0 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -1,5 +1 @@
-//= include ../../../bower_components/jquery/dist/jquery.js
-
-(function() {
- console.log("Hello world");
-})();
+$(() => GOVUK.modules.start());
diff --git a/app/assets/stylesheets/components/textbox.scss b/app/assets/stylesheets/components/textbox.scss
new file mode 100644
index 000000000..1d2807709
--- /dev/null
+++ b/app/assets/stylesheets/components/textbox.scss
@@ -0,0 +1,83 @@
+.textbox-highlight {
+
+ &-wrapper {
+ position: relative;
+ }
+
+ &-textbox {
+ resize: none;
+ z-index: 20;
+ background: none;
+ }
+
+ &-textbox,
+ &-background,
+ &-foreground,
+ &-mask {
+ @include core-19;
+ display: block;
+ box-sizing: border-box;
+ position: relative;
+ width: 500px;
+ height: 200px;
+ margin: 0;
+ padding: 4px;
+ overflow: hidden;
+ }
+
+ &-background,
+ &-foreground,
+ &-mask {
+ position: absolute;
+ top: 0;
+ left: 0;
+ pointer-events: none;
+ color: transparent;
+ white-space: pre-wrap;
+ border: 2px solid transparent;
+ }
+
+ &-background {
+
+ z-index: 10;
+
+ .tag {
+ background: $light-blue;
+ border-radius: 3px;
+ color: transparent;
+ display: inline;
+ }
+
+ }
+
+ &-mask {
+
+ z-index: 30;
+
+ .tag {
+ color: $white;
+ text-shadow: 0 1px 0 $light-blue, 0 -1px 0 $light-blue;
+ position: relative;
+ display: inline;
+ overflow: hidden;
+ }
+
+ }
+
+ &-foreground {
+
+ z-index: 40;
+
+ .tag {
+ color: transparent;
+ border-radius: 3px;
+ overflow: hidden;
+ display: inline;
+ box-shadow: inset 0.75em 0 0 0 rgba($light-blue, .7),
+ inset -0.75em 0 0 0 rgba($light-blue, .7);
+ }
+
+ }
+
+
+}
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index 13ac54a99..ece58780a 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -38,6 +38,7 @@
@import 'components/navigation';
@import 'components/big-number';
@import 'components/banner';
+@import 'components/textbox';
@import 'views/job';
diff --git a/app/main/__init__.py b/app/main/__init__.py
index a7134aef1..7b77dcc48 100644
--- a/app/main/__init__.py
+++ b/app/main/__init__.py
@@ -4,5 +4,5 @@ main = Blueprint('main', __name__)
from app.main.views import (
- index, sign_in, register, two_factor, verify, sms, add_service, code_not_received, jobs, dashboard
+ index, sign_in, register, two_factor, verify, sms, add_service, code_not_received, jobs, dashboard, templates
)
diff --git a/app/main/views/index.py b/app/main/views/index.py
index d3f2f7c16..9c9ef1f6c 100644
--- a/app/main/views/index.py
+++ b/app/main/views/index.py
@@ -64,11 +64,6 @@ def apikeys():
return render_template('views/api-keys.html')
-@main.route("/manage-templates")
-def managetemplates():
- return render_template('views/manage-templates.html')
-
-
-@main.route("/edit-template")
-def edittemplate():
- return render_template('views/edit-template.html')
+@main.route("/verification-not-received")
+def verificationnotreceived():
+ return render_template('views/verification-not-received.html')
diff --git a/app/main/views/templates.py b/app/main/views/templates.py
new file mode 100644
index 000000000..ff80cb353
--- /dev/null
+++ b/app/main/views/templates.py
@@ -0,0 +1,32 @@
+from flask import request, render_template, redirect, url_for
+
+from app.main import main
+
+
+@main.route("/templates")
+def manage_templates():
+ return render_template('views/manage-templates.html')
+
+
+@main.route("/templates/template", methods=['GET', 'POST'])
+def add_template():
+ if request.method == 'GET':
+ return render_template(
+ 'views/edit-template.html',
+ template_name='Reminder',
+ template_body='Vehicle tax: Your vehicle tax for ((registration number)) expires on ((date)). Tax your vehicle at www.gov.uk/vehicle-tax', # noqa
+ h1='Edit template'
+ )
+ elif request.method == 'POST':
+ return redirect(url_for('.manage_templates'))
+
+
+@main.route("/templates/template/add", methods=['GET', 'POST'])
+def edit_template():
+ if request.method == 'GET':
+ return render_template(
+ 'views/edit-template.html',
+ h1='Add template'
+ )
+ elif request.method == 'POST':
+ return redirect(url_for('.manage_templates'))
diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html
index bff13ff6f..76947a435 100644
--- a/app/templates/admin_template.html
+++ b/app/templates/admin_template.html
@@ -47,5 +47,5 @@
{% endblock %}
{% block body_end %}
-
+
{% endblock %}
diff --git a/app/templates/components/submit-form.html b/app/templates/components/submit-form.html
index cd879a238..012d0a580 100644
--- a/app/templates/components/submit-form.html
+++ b/app/templates/components/submit-form.html
@@ -1,11 +1,9 @@
-{% macro submit_form(button_text, back_link) %}
+{% macro submit_form(button_text, back_link=False) %}
{% endmacro %}
diff --git a/app/templates/components/textbox.html b/app/templates/components/textbox.html
new file mode 100644
index 000000000..a32a76c4b
--- /dev/null
+++ b/app/templates/components/textbox.html
@@ -0,0 +1,15 @@
+{% macro textbox(name, label, value='', small=True, highlight_tags=False) %}
+
+
+ {% if small %}
+
+ {% else %}
+
+ {% endif %}
+
+{% endmacro %}
diff --git a/app/templates/views/check-sms.html b/app/templates/views/check-sms.html
index 104d1d075..b3277f09e 100644
--- a/app/templates/views/check-sms.html
+++ b/app/templates/views/check-sms.html
@@ -15,50 +15,54 @@
Check and confirm
- {{ submit_form(
- "Send {} text messages".format(number_of_recipients),
- url_for(".sendsms")
- ) }}
+
diff --git a/app/templates/views/edit-template.html b/app/templates/views/edit-template.html
index ed29b8074..b17b5b64c 100644
--- a/app/templates/views/edit-template.html
+++ b/app/templates/views/edit-template.html
@@ -1,4 +1,6 @@
{% extends "withnav_template.html" %}
+{% from "components/textbox.html" import textbox %}
+{% from "components/submit-form.html" import submit_form %}
{% block page_title %}
GOV.UK Notify | Edit template
@@ -6,13 +8,14 @@ GOV.UK Notify | Edit template
{% block maincolumn_content %}
+ {{ h1 }}
- Edit template
-
- Here's where you can edit an exiting template (including delete) or add a new one
+
Back to manage templates
-
-
{% endblock %}
diff --git a/app/templates/views/job.html b/app/templates/views/job.html
index 2cfd7a74e..963ff1810 100644
--- a/app/templates/views/job.html
+++ b/app/templates/views/job.html
@@ -13,7 +13,9 @@ GOV.UK Notify | Notifications activity
{{ uploaded_file_name }}
+
{{ banner(flash_message) }}
+
-
@@ -36,7 +38,7 @@ GOV.UK Notify | Notifications activity
- Sent with template {{ template_used }} at {{ uploaded_file_time }}
+ Sent with template {{ template_used }} at {{ uploaded_file_time }}
{% call(item) table(
diff --git a/app/templates/views/manage-templates.html b/app/templates/views/manage-templates.html
index 1554f3b09..4c4fa8d88 100644
--- a/app/templates/views/manage-templates.html
+++ b/app/templates/views/manage-templates.html
@@ -7,15 +7,17 @@ GOV.UK Notify | Manage templates
{% block maincolumn_content %}
- Manage templates
+ Manage templates
- Here's where you can view templates, choose to add one, or edit/delete one.
+ Here's where you can view templates, choose to add one, or edit/delete one.
- Here is my first template
+
+ Here is my first template
+
-
- Add a new message template
-
+
+ Add a new message template
+
{% endblock %}
diff --git a/app/templates/views/send-sms.html b/app/templates/views/send-sms.html
index ce07dc69e..75d81ffeb 100644
--- a/app/templates/views/send-sms.html
+++ b/app/templates/views/send-sms.html
@@ -24,7 +24,7 @@
{% endfor %}
- or create a new template
+ or create a new template
2. Add recipients
diff --git a/bower.json b/bower.json
index 312bf3293..efa72b2c5 100644
--- a/bower.json
+++ b/bower.json
@@ -2,7 +2,6 @@
"name": "GOV.UK Notify admin frontend",
"version": "0.0.1",
"dependencies": {
- "jquery": "1.11.2",
"govuk_template": "https://github.com/alphagov/govuk_template/releases/download/v0.16.0/jinja_govuk_template-0.16.0.tgz"
}
}
diff --git a/gulpfile.babel.js b/gulpfile.babel.js
new file mode 100644
index 000000000..48b7e14a8
--- /dev/null
+++ b/gulpfile.babel.js
@@ -0,0 +1,89 @@
+// GULPFILE
+// - - - - - - - - - - - - - - -
+// This file processes all of the assets in the "src" folder
+// and outputs the finished files in the "dist" folder.
+
+// 1. LIBRARIES
+// - - - - - - - - - - - - - - -
+var gulp = require('gulp'),
+ plugins = require('gulp-load-plugins')(),
+
+// 2. CONFIGURATION
+// - - - - - - - - - - - - - - -
+ paths = {
+ src: 'app/assets/',
+ dist: 'app/static/',
+ templates: 'app/templates/'
+ };
+
+// 3. TASKS
+// - - - - - - - - - - - - - - -
+
+// Move GOV.UK template resources
+
+gulp.task('copy:govuk_template:template', () => gulp.src('bower_components/govuk_template/views/layouts/govuk_template.html')
+ .pipe(gulp.dest(paths.templates))
+);
+
+gulp.task('copy:govuk_template:assets', () => gulp.src('bower_components/govuk_template/assets/**/*')
+ .pipe(gulp.dest(paths.dist))
+);
+
+
+// Concatenate and minify
+
+gulp.task('jquery', () => plugins.jquery.src({
+ release: 1,
+ flags: [
+ '-ajax', '-ajax/jsonp', '-ajax/load', '-ajax/parseJSON',
+ '-ajax/parseXML', '-ajax/script', '-ajax/var/nonce',
+ '-ajax/var/rquery', '-ajax/xhr', '-manipulation/_evalUrl',
+ '-deprecated', '-effects', '-effects/Tween',
+ '-effects/animatedSelector', '-effects/support', '-event-alias'
+ ]
+ })
+ .pipe(gulp.dest(paths.dist + 'javascripts/'))
+);
+
+gulp.task('javascripts', () => gulp.src([
+ paths.src + 'govuk_frontend_toolkit/javascripts/govuk/modules.js',
+ paths.src + 'javascripts/highlightTags.js',
+ paths.src + 'javascripts/main.js'
+ ])
+ .pipe(plugins.babel({
+ presets: ['es2015']
+ }))
+ .pipe(plugins.uglify())
+ .pipe(plugins.concat('all.js'))
+ .pipe(gulp.dest(paths.dist + 'javascripts/'))
+);
+
+gulp.task('sass', () => gulp.src(paths.src + '/stylesheets/main*.scss')
+ .pipe(plugins.sass({outputStyle: 'compressed'}))
+ .pipe(gulp.dest(paths.dist + '/stylesheets'))
+);
+
+
+// Copy images
+
+gulp.task('images', () => gulp.src(paths.src + 'images/**/*')
+ .pipe(gulp.dest(paths.dist + '/images'))
+);
+
+
+// Watch for changes and re-run tasks
+gulp.task('watchForChanges', function() {
+ gulp.watch(paths.src + 'javascripts/**/*', ['javascripts']);
+ gulp.watch(paths.src + 'stylesheets/**/*', ['sass']);
+ gulp.watch(paths.src + 'images/**/*', ['images']);
+});
+
+// Default: compile everything
+gulp.task('default',
+ ['copy:govuk_template:template', 'copy:govuk_template:assets', 'javascripts', 'sass', 'images']
+);
+
+// Optional: recompile on changes
+gulp.task('watch',
+ ['default', 'watchForChanges']
+);
diff --git a/gulpfile.js b/gulpfile.js
deleted file mode 100644
index f480f2bc7..000000000
--- a/gulpfile.js
+++ /dev/null
@@ -1,77 +0,0 @@
-// GULPFILE
-// - - - - - - - - - - - - - - -
-// This file processes all of the assets in the "src" folder
-// and outputs the finished files in the "dist" folder.
-
-// 1. LIBRARIES
-// - - - - - - - - - - - - - - -
-var gulp = require('gulp'),
- plugins = require('gulp-load-plugins')(),
-
-// 2. CONFIGURATION
-// - - - - - - - - - - - - - - -
- paths = {
- src: 'app/assets/',
- dist: 'app/static/',
- templates: 'app/templates/'
- };
-
-// 3. TASKS
-// - - - - - - - - - - - - - - -
-
-// Move GOV.UK template resources
-
-gulp.task('copy:govuk_template:template', function() {
- return gulp.src('bower_components/govuk_template/views/layouts/govuk_template.html')
- .pipe(gulp.dest(paths.templates));
-});
-
-gulp.task('copy:govuk_template:assets', function() {
- return gulp.src('bower_components/govuk_template/assets/**/*')
- .pipe(gulp.dest(paths.dist));
-});
-
-
-// Concatenate and minify
-
-gulp.task('javascripts', function() {
- return gulp.src(paths.src + 'javascripts/main.js')
- .pipe(plugins.include())
- .pipe(gulp.dest(paths.dist + 'javascripts/'))
- .pipe(plugins.uglify())
- .on('error', function(e) { console.log("Uglify did not complete."); })
- .pipe(gulp.dest(paths.dist + 'javascripts/'));
-
-});
-
-gulp.task('sass', function () {
- return gulp.src(paths.src + '/stylesheets/main*.scss')
- .pipe(plugins.sass({outputStyle: 'compressed'}))
- .pipe(gulp.dest(paths.dist + '/stylesheets'));
-});
-
-
-// Copy images
-
-gulp.task('images', function() {
- return gulp.src(paths.src + 'images/**/*')
- .pipe(gulp.dest(paths.dist + '/images'));
-});
-
-
-// Watch for changes and re-run tasks
-gulp.task('watchForChanges', function() {
- gulp.watch(paths.src + 'javascripts/**/*', ['javascripts']);
- gulp.watch(paths.src + 'stylesheets/**/*', ['sass']);
- gulp.watch(paths.src + 'images/**/*', ['images']);
-});
-
-// Default: compile everything
-gulp.task('default',
- ['copy:govuk_template:template', 'copy:govuk_template:assets', 'javascripts', 'sass', 'images']
-);
-
-// Optional: recompile on changes
-gulp.task('watch',
- ['default', 'watchForChanges']
-);
diff --git a/package.json b/package.json
index 20c6dd27a..fd1abafc5 100644
--- a/package.json
+++ b/package.json
@@ -2,6 +2,9 @@
"name": "notifications-admin",
"version": "0.0.1",
"description": "Admin front end for GOV.UK Notify",
+ "engines": {
+ "node": "5.0.0"
+ },
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"postinstall": "./node_modules/bower/bin/bower install && npm run build",
@@ -16,11 +19,18 @@
"license": "MIT",
"homepage": "https://github.com/alphagov/notifications-admin#readme",
"dependencies": {
+ "babel-core": "6.3.26",
+ "babel-preset-es2015": "6.3.13",
"bower": "1.7.1",
"gulp": "3.9.0",
+ "gulp-add-src": "0.2.0",
+ "gulp-babel": "6.1.1",
+ "gulp-concat": "2.6.0",
"gulp-include": "2.1.0",
+ "gulp-jquery": "1.1.1",
"gulp-load-plugins": "1.1.0",
"gulp-sass": "2.1.1",
- "gulp-uglify": "1.5.1"
+ "gulp-uglify": "1.5.1",
+ "jquery": "1.11.2"
}
}
diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py
new file mode 100644
index 000000000..219c3ad41
--- /dev/null
+++ b/tests/app/main/views/test_templates.py
@@ -0,0 +1,17 @@
+def test_should_return_list_of_all_templates(notifications_admin):
+ response = notifications_admin.test_client().get('/templates')
+
+ assert response.status_code == 200
+
+
+def test_should_show_page_for_one_templates(notifications_admin):
+ response = notifications_admin.test_client().get('/templates/template')
+
+ assert response.status_code == 200
+
+
+def test_should_redirect_when_saving_a_template(notifications_admin):
+ response = notifications_admin.test_client().post('/templates/template')
+
+ assert response.status_code == 302
+ assert response.location == 'http://localhost/templates'