diff --git a/.gitignore b/.gitignore index 0a21cad9f..c84489e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -58,10 +58,12 @@ target/ .idea/ .DS_Store -# cache and static rebuild files +# Frontend dependencies and compiled assets app/assets/stylesheets/govuk_template/.sass-cache/ .sass-cache/ cache/ -app/static/* -app/static/stylesheets/*.css - +app/static +node_modules +bower_components +app/templates/govuk_template.html +npm-debug.log diff --git a/.gitmodules b/.gitmodules index 698b9d0b6..090878d9d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "app/assets/stylesheets/govuk_frontend_toolkit"] - path = app/assets/stylesheets/govuk_frontend_toolkit + path = app/assets/govuk_frontend_toolkit url = https://github.com/alphagov/govuk_frontend_toolkit.git [submodule "app/assets/stylesheets/govuk_elements"] - path = app/assets/stylesheets/govuk_elements + path = app/assets/govuk_elements url = https://github.com/alphagov/govuk_elements.git diff --git a/.travis.yml b/.travis.yml index 24b59df39..f7d0352be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,10 @@ 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: -- bundle install +- npm install - pip install -r requirements_for_test.txt before_script: - psql -c 'create database test_notifications_admin;' -U postgres diff --git a/Gemfile b/Gemfile deleted file mode 100644 index e46ea120f..000000000 --- a/Gemfile +++ /dev/null @@ -1,2 +0,0 @@ -source 'https://rubygems.org' -gem 'sass' diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index bb229915d..000000000 --- a/Gemfile.lock +++ /dev/null @@ -1,13 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - sass (3.4.19) - -PLATFORMS - ruby - -DEPENDENCIES - sass - -BUNDLED WITH - 1.10.6 diff --git a/Procfile b/Procfile index 33594db01..bd846ba9a 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: python app.py runserver \ No newline at end of file +web: python app.py runserver diff --git a/README.md b/README.md index 82d20a527..5cf8f501b 100644 --- a/README.md +++ b/README.md @@ -14,32 +14,49 @@ Application to handle the admin functions of the notifications application. ### Create a virtual environment for this project - mkvirtualenv -p /usr/local/bin/python3 notifications-admin - +```shell + mkvirtualenv -p /usr/local/bin/python3 notifications-admin +``` -### GOV.UK frontend toolkit - The GOV.UK frontend toolkit is a submodule of this project. - To get the content of the toolkit run the following two commands - - git submodule init - git submodule update + +### Building the frontend + +You need [Node](http://nodejs.org/) which will also get you [NPM](npmjs.org), +Node's package management tool. +```shell + brew install node +``` + +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 +```shell + git submodule init --update + npm install +``` + +If you want the front end assets to re-compile on changes, leave this running +in a separate terminal from the app +```shell + npm run watch +``` ### Running the application: +```shell pip install -r requirements.txt ./scripts/bootstrap.sh ./scripts/run_app.sh +``` -Note: the ./scripts/bootstrap.sh script only needs to be run the first time to create the database. +Note: the ./scripts/bootstrap.sh script only needs to be run the first time to +create the database. + +URL to test app: - url to test app: - localhost:6012/helloworld ### Domain model -All the domain models are defined in the [models.py](https://github.com/alphagov/notifications-admin/blob/master/app/models.py) file. - - - - +All the domain models are defined in the +[models.py](https://github.com/alphagov/notifications-admin/blob/master/app/models.py) +file. diff --git a/app.py b/app.py index e69af42b5..dc26c70cc 100644 --- a/app.py +++ b/app.py @@ -1,8 +1,6 @@ import os -from flask.ext import assets from flask.ext.script import Manager, Server from flask_migrate import Migrate, MigrateCommand -from webassets.filter import get_filter from app import create_app, db diff --git a/app/__init__.py b/app/__init__.py index cc3705a93..498230fe3 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -3,11 +3,9 @@ import re from flask import Flask, session, Markup from flask._compat import string_types -from flask.ext import assets from flask.ext.sqlalchemy import SQLAlchemy from flask_login import LoginManager from flask_wtf import CsrfProtect -from webassets.filter import get_filter from werkzeug.exceptions import abort from app.notify_client.api_client import AdminAPIClient @@ -75,78 +73,9 @@ def init_app(app): if key in os.environ: app.config[key] = convert_to_boolean(os.environ[key]) - init_asset_environment(app) - - -def init_asset_environment(app): - env = assets.Environment(app) - - # Tell flask-assets where to look for our sass files. - env.load_path = [ - os.path.join(os.path.dirname(__file__), 'assets'), - os.path.join(os.path.dirname(__file__), 'assets/stylesheets'), - os.path.join(os.path.dirname(__file__), 'assets/stylesheets/stylesheets/govuk_frontend_toolkit'), - os.path.join(os.path.dirname(__file__), 'assets/stylesheets/govuk_template'), - os.path.join(os.path.dirname(__file__), 'assets/stylesheets/views'), - os.path.join(os.path.dirname(__file__), 'assets/stylesheets/components'), - ] - - scss = get_filter('scss', as_output=True) - - env.register( - 'css_all', - assets.Bundle( - 'main.scss', - filters='scss', - output='stylesheets/css_all.css' - ) - ) - - env.register( - 'css_govuk-template', - assets.Bundle( - 'govuk_template/govuk-template.scss', - filters='scss', - output='stylesheets/govuk-template.css', - depends='*.scss' - ) - ) - - env.register( - 'css_govuk-template-ie6', - assets.Bundle( - 'govuk_template/govuk-template-ie6.scss', - filters='scss', - output='stylesheets/govuk-template-ie6.css' - ) - ) - - env.register( - 'css_govuk-template-ie7', - assets.Bundle( - 'govuk_template/govuk-template-ie7.scss', - filters='scss', - output='stylesheets/govuk-template-ie7.css' - ) - ) - - env.register( - 'css_govuk-template-ie8', - assets.Bundle( - 'govuk_template/govuk-template-ie8.scss', - filters='scss', - output='stylesheets/govuk-template-ie8.css' - ) - ) - - env.register( - 'css_govuk-template-print', - assets.Bundle( - 'govuk_template/govuk-template-print.scss', - filters='scss', - output='stylesheets/govuk-template-print.css' - ) - ) + @app.context_processor + def inject_global_template_variables(): + return {'asset_path': '/static/'} def convert_to_boolean(value): diff --git a/app/assets/images/apple-touch-icon-120x120.png b/app/assets/images/apple-touch-icon-120x120.png deleted file mode 100644 index 7cb519ac2..000000000 Binary files a/app/assets/images/apple-touch-icon-120x120.png and /dev/null differ diff --git a/app/assets/images/apple-touch-icon-152x152.png b/app/assets/images/apple-touch-icon-152x152.png deleted file mode 100644 index 4a0b722c7..000000000 Binary files a/app/assets/images/apple-touch-icon-152x152.png and /dev/null differ diff --git a/app/assets/images/apple-touch-icon-60x60.png b/app/assets/images/apple-touch-icon-60x60.png deleted file mode 100644 index 4a78153fe..000000000 Binary files a/app/assets/images/apple-touch-icon-60x60.png and /dev/null differ diff --git a/app/assets/images/apple-touch-icon-76x76.png b/app/assets/images/apple-touch-icon-76x76.png deleted file mode 100644 index 54f7023ef..000000000 Binary files a/app/assets/images/apple-touch-icon-76x76.png and /dev/null differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico deleted file mode 100644 index da3760d3b..000000000 Binary files a/app/assets/images/favicon.ico and /dev/null differ diff --git a/app/assets/images/gov.uk_logotype_crown_invert.png b/app/assets/images/gov.uk_logotype_crown_invert.png deleted file mode 100644 index d7c0e929c..000000000 Binary files a/app/assets/images/gov.uk_logotype_crown_invert.png and /dev/null differ diff --git a/app/assets/images/gov.uk_logotype_crown_invert_trans.png b/app/assets/images/gov.uk_logotype_crown_invert_trans.png deleted file mode 100644 index 152b83eab..000000000 Binary files a/app/assets/images/gov.uk_logotype_crown_invert_trans.png and /dev/null differ diff --git a/app/assets/images/opengraph-image.png b/app/assets/images/opengraph-image.png deleted file mode 100644 index 355284fbf..000000000 Binary files a/app/assets/images/opengraph-image.png and /dev/null differ diff --git a/app/assets/javascripts/govuk-template.js b/app/assets/javascripts/govuk-template.js deleted file mode 100644 index 050133013..000000000 --- a/app/assets/javascripts/govuk-template.js +++ /dev/null @@ -1,112 +0,0 @@ -(function () { - "use strict" - var root = this; - if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; } - - /* - Cookie methods - ============== - - Usage: - - Setting a cookie: - GOVUK.cookie('hobnob', 'tasty', { days: 30 }); - - Reading a cookie: - GOVUK.cookie('hobnob'); - - Deleting a cookie: - GOVUK.cookie('hobnob', null); - */ - GOVUK.cookie = function (name, value, options) { - if(typeof value !== 'undefined'){ - if(value === false || value === null) { - return GOVUK.setCookie(name, '', { days: -1 }); - } else { - return GOVUK.setCookie(name, value, options); - } - } else { - return GOVUK.getCookie(name); - } - }; - GOVUK.setCookie = function (name, value, options) { - if(typeof options === 'undefined') { - options = {}; - } - var cookieString = name + "=" + value + "; path=/"; - if (options.days) { - var date = new Date(); - date.setTime(date.getTime() + (options.days * 24 * 60 * 60 * 1000)); - cookieString = cookieString + "; expires=" + date.toGMTString(); - } - if (document.location.protocol == 'https:'){ - cookieString = cookieString + "; Secure"; - } - document.cookie = cookieString; - }; - GOVUK.getCookie = function (name) { - var nameEQ = name + "="; - var cookies = document.cookie.split(';'); - for(var i = 0, len = cookies.length; i < len; i++) { - var cookie = cookies[i]; - while (cookie.charAt(0) == ' ') { - cookie = cookie.substring(1, cookie.length); - } - if (cookie.indexOf(nameEQ) === 0) { - return decodeURIComponent(cookie.substring(nameEQ.length)); - } - } - return null; - }; -}).call(this); -(function () { - "use strict" - var root = this; - if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; } - - GOVUK.addCookieMessage = function () { - var message = document.getElementById('global-cookie-message'), - hasCookieMessage = (message && GOVUK.cookie('seen_cookie_message') === null); - - if (hasCookieMessage) { - message.style.display = 'block'; - GOVUK.cookie('seen_cookie_message', 'yes', { days: 28 }); - } - }; -}).call(this); -(function() { - "use strict" - - // add cookie message - if (window.GOVUK && GOVUK.addCookieMessage) { - GOVUK.addCookieMessage(); - } - - // header navigation toggle - if (document.querySelectorAll && document.addEventListener){ - var els = document.querySelectorAll('.js-header-toggle'), - i, _i; - for(i=0,_i=els.length; i<_i; i++){ - els[i].addEventListener('click', function(e){ - e.preventDefault(); - var target = document.getElementById(this.getAttribute('href').substr(1)), - targetClass = target.getAttribute('class') || '', - sourceClass = this.getAttribute('class') || ''; - - if(targetClass.indexOf('js-visible') !== -1){ - target.setAttribute('class', targetClass.replace(/(^|\s)js-visible(\s|$)/, '')); - } else { - target.setAttribute('class', targetClass + " js-visible"); - } - if(sourceClass.indexOf('js-hidden') !== -1){ - this.setAttribute('class', sourceClass.replace(/(^|\s)js-hidden(\s|$)/, '')); - } else { - this.setAttribute('class', sourceClass + " js-hidden"); - } - }); - } - } -}).call(this); - - - 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 = $(` +