Merge pull request #27 from alphagov/send-sms-flow

Put elements on pages for ‘send text messages’ flow
This commit is contained in:
minglis
2015-12-14 10:40:55 +00:00
82 changed files with 632 additions and 4043 deletions

5
.gitignore vendored
View File

@@ -62,7 +62,4 @@ target/
app/assets/stylesheets/govuk_template/.sass-cache/
.sass-cache/
cache/
app/static/stylesheets/govuk-template*
app/static/css*
app/static/css_all.css
app/static/.webassets-cache/
app/static/*

7
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "app/assets/govuk_frontend_toolkit"]
path = app/assets/govuk_frontend_toolkit
[submodule "app/assets/stylesheets/govuk_frontend_toolkit"]
path = app/assets/stylesheets/govuk_frontend_toolkit
url = https://github.com/alphagov/govuk_frontend_toolkit.git
[submodule "app/assets/stylesheets/govuk_elements"]
path = app/assets/stylesheets/govuk_elements
url = https://github.com/alphagov/govuk_elements.git

View File

@@ -7,6 +7,7 @@ addons:
env:
- SQLALCHEMY_DATABASE_URI=postgresql://postgres:@localhost:5433/test_notifications_admin
install:
- bundle install
- pip install -r requirements_for_test.txt
env:
secure: jT9BIioqBMkOdLZhU+WJNdnRJ+06G7qUx4QqEVldp96dJwmWpPEvA0XbitdnQt/WXYkpMlDbgSApvvGj2ZNvdpowRRe5HFX8D2Udhi2g9+cXgKrQxH6zv0evJyQLOjCINW6KtgMCJ5wkYR3qQ4BQawlDt6ecpmeboKTmvs2W8jZ09aV4IKKvdd7BwFon10QVPF5ny10G83unLtKnKgRMjSSLnaEiA78pE/LSUkekK4mhmtl+yfQf60cIuQGcN9NCYIt5PrdYYyMkbUaht9ykwL2C11sp5JYPClI9k6lrlpGJCdL9wbJwejGhR/pEqwJ4tKK8Zv+mngmkbzE6fd5ehuRMnIUAifG4t3p6WbhKwY5pJsdVyPgWcRSPXOJA7yEcAeTAvWcC++6mCIFBeMxt/yQNw02jkFHeNKRh2twTRvr4xWZHq9FsVxTEVz89OOuue3IkkyDNmVusGJ9+AVRIn9Oa+U/r3bDnrs7jz+meSwb82GZUBzFpUe2pe8qeBE572Ay7yHB73VHUgp/2A1qkZ4SnTjTpMbnS5RdXTgwtMkOs5MLZgteCVxFL3sHcr9e/B3UIUnzKUSPXXOjHyDxBwrABWo81V9Vp2IPV7P9Ofv8zroudjQxK5MOcbmiPQF+eEB9L4DvkUBNsGxtJ/nmPp6tmN0Xjo0xXVdZCEVj29Og=

View File

@@ -1,2 +1,2 @@
source 'https://rubygems.org'
gem 'sass'
gem 'sass'

View File

@@ -1,6 +1,7 @@
import os
import re
from flask import Flask, session
from flask import Flask, session, Markup
from flask._compat import string_types
from flask.ext import assets
from flask.ext.sqlalchemy import SQLAlchemy
@@ -44,6 +45,9 @@ def create_app(config_name):
application.session_interface = ItsdangerousSessionInterface()
admin_api_client.init_app(application)
application.add_template_filter(placeholders)
application.add_template_filter(replace_placeholders)
return application
@@ -79,11 +83,12 @@ def init_asset_environment(app):
# Tell flask-assets where to look for our sass files.
env.load_path = [
os.path.join(os.path.dirname(__file__), 'assets/stylesheets'),
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/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)
@@ -93,7 +98,7 @@ def init_asset_environment(app):
assets.Bundle(
'main.scss',
filters='scss',
output='css_all.css'
output='stylesheets/css_all.css'
)
)
@@ -152,3 +157,23 @@ def convert_to_boolean(value):
return False
return value
def placeholders(value):
if not value:
return value
return Markup(re.sub(
r"\(\(([^\)]+)\)\)", # anything that looks like ((registration number))
lambda match: "<span class='placeholder'>{}</span>".format(match.group(1)),
value
))
def replace_placeholders(template, values):
if not template:
return template
return Markup(re.sub(
r"\(\(([^\)]+)\)\)", # anything that looks like ((registration number))
lambda match: values.get(match.group(1), ''),
template
))

View File

@@ -0,0 +1,8 @@
.placeholder {
display: inline;
background: $light-blue;
color: $white;
white-space: nowrap;
padding: 0 5px;
border-radius: 3px;
}

View File

@@ -0,0 +1,47 @@
.sms-message {
position: relative;
margin: 0 0 $gutter 0;
&:before {
content: '';
position: absolute;
z-index: 10;
bottom: -12px;
right: 5px;
width: 20px;
height: 25px;
border-radius: 100%;
background: $panel-colour;
}
&:after {
content: '';
position: absolute;
z-index: 20;
bottom: -15px;
right: -5px;
border-radius: 100%;
width: 20px;
height: 20px;
background: $white;
}
&-wrapper {
display: inline-block;
box-sizing: border-box;
position: relative;
z-index: 30;
padding: $gutter/2;
background: $panel-colour;
border-radius: 5px;
white-space: normal;
}
&-recipient {
@include copy-19;
color: $secondary-text-colour;
margin: 0;
}
}

View File

@@ -0,0 +1,12 @@
.submit-form {
margin-bottom: 50px;
&-back-link {
@include button($grey-1);
padding: 0.52632em 0.78947em 0.26316em 0.78947em;
@include inline-block;
margin-left: 5px;
}
}

View File

@@ -0,0 +1,7 @@
.table {
&-heading {
text-align: left;
}
}

View File

@@ -0,0 +1,33 @@
.template-picker {
&-name {
@include bold-19;
padding-left: 5px;
}
&-option {
white-space: nowrap;
clear: both;
&-radio {
padding-right: 10px;
box-sizing: border-box;
vertical-align: top;
width: 33%;
display: inline-block;
}
.block-label {
display: inline-block;
}
.sms-message {
display: inline-block;
vertical-align: top;
max-width: 66%;
}
}
}

View File

@@ -1,5 +0,0 @@
$is-ie: true;
$ie-version: 6;
$mobile-ie6: false;
@import "elements-page";

View File

@@ -1,4 +0,0 @@
$is-ie: true;
$ie-version: 7;
@import "elements-page";

View File

@@ -1,4 +0,0 @@
$is-ie: true;
$ie-version: 8;
@import "elements-page";

View File

@@ -1,380 +0,0 @@
@import "main";
// ==========================================================================
// Elements page styles
// ==========================================================================
// These are example styles, used only for the elements pages
.elements-index {
// Reduce top and bottom margins
.heading-medium {
margin: 1em 0 0 0;
}
// Add spacing above
.divider {
margin-top: 4em;
}
}
// Increase spacing above headings
.heading-xlarge {
@include media(tablet) {
margin-top: em(60, 48);
margin-bottom: em(30, 48);
}
}
// Page contents
.heading-contents {
margin-top: 3em;
}
.list-contents li {
@include core-16;
}
// Use for paragraphs before lists
.lead-in {
margin-bottom: 0;
}
// Lists
.list-bullet {
margin-bottom: ($gutter*1.5);
}
// Example boxes
// ==========================================================================
.example {
@extend %contain-floats;
position: relative;
overflow: hidden;
border: 1px solid $grey-2;
margin-top: $gutter-half;
margin-bottom: $gutter-half;
padding-top: $gutter;
padding-right: $gutter-half;
padding-bottom: $gutter-half;
padding-left: $gutter-half;
@include media(tablet) {
padding-top: $gutter*1.5;
padding-right: $gutter;
padding-bottom: $gutter;
padding-left: $gutter;
}
&:before {
content: "EXAMPLE";
position: absolute;
top: 0;
left: 0;
padding: em(4) em(15) em(4) em(15);
@include core-14;
background: $grey-2;
color: white;
}
// Blue text for heading sizes
.highlight {
font-style: normal;
color: $hm-government;
}
// Fix grid layout within example boxes for IE7 and below
// where box-sizing isn't supported: http://caniuse.com/#search=box-sizing
@mixin example-box-column($width) {
width: (($site-width - $gutter) * $width) - $gutter;
}
@include ie-lte(7){
// Set example box width to 900px (removing left and right padding)
$example-box-width: $site-width - ($gutter * 2);
width: $example-box-width;
// Recalculate grid column widths
.column-quarter {
@include example-box-column( 1/4 );
}
.column-half {
@include example-box-column( 1/2 );
}
.column-third {
@include example-box-column( 1/3 );
}
.column-two-thirds {
@include example-box-column( 2/3 );
}
// Scale images to fit grid columns
img {
width: 100%;
}
}
}
// 1. Layout
// ==========================================================================
.example-grid p {
width: 100%;
background: file-url("examples/grid.png") 0 0 repeat;
margin-bottom: 0;
height: 30px;
@include media(tablet) {
height: 60px;
}
overflow: hidden;
text-indent: -999em;
}
// 2. Typography
// ==========================================================================
// 3. Colour
// ==========================================================================
// Colour swatches
.swatch {
width: 60px;
height: 60px;
@include border-radius(100%);
@include media(mobile) {
clear: both;
float: left;
margin-right: $gutter-half;
margin-bottom: $gutter-half;
}
@include media(tablet) {
margin: 0 auto $gutter-half auto;
}
}
// Sass list for colour palette
$palette: (
("purple", $purple),
("mauve", $mauve),
("fuschia", $fuschia),
("pink", $pink),
("baby-pink", $baby-pink),
("red", $red),
("mellow-red", $mellow-red),
("orange", $orange),
("brown", $brown),
("yellow", $yellow),
("green", $green),
("grass-green", $grass-green),
("turquoise", $turquoise),
("light-blue", $light-blue)
);
@mixin color-swatches {
@each $color in $palette {
$color-name: nth($color, 1);
$color-var: nth($color, 2);
.swatch-#{$color-name} {
background-color: $color-var;
}
}
}
// Generate swatch classes for each colour in palette list
@include color-swatches;
.swatch-alpha {
background-color: $alpha-colour;
}
.swatch-beta {
background-color: $beta-colour;
}
.swatch-discovery {
background-color: $discovery-colour;
}
.swatch-live {
background-color: $live-colour;
}
.swatch-error {
background-color: $error-colour;
}
.swatch-focus {
background-color: $focus-colour;
}
.swatch-button-colour {
background-color: $button-colour;
}
.swatch-black {
background-color: $black;
}
.swatch-grey-1 {
background-color: $grey-1;
}
.swatch-grey-2 {
background-color: $grey-2;
}
.swatch-grey-3 {
background-color: $grey-3;
}
.swatch-grey-4 {
background-color: $grey-4;
}
.swatch-white {
background-color: $white;
border: 1px solid $grey-3;
}
.swatch-text-colour {
background-color: $text-colour;
}
.swatch-text-secondary {
background-color: $secondary-text-colour;
}
.swatch-page-colour {
background-color: $page-colour;
border: 1px solid $grey-3;
}
.swatch-button-colour {
background-color: $button-colour;
}
.swatch-link-colour {
background-color: $link-colour;
}
.swatch-link-colour-visited {
background-color: $link-visited-colour;
}
.swatch-link-colour-hover {
background-color: $link-hover-colour;
}
.swatch-border-colour {
background-color: $border-colour;
}
.swatch-panel-colour {
background-color: $panel-colour;
}
.swatch-highlight-colour {
background-color: $highlight-colour;
}
// Colour swatch layout
.swatch-wrapper {
@include media(tablet) {
float: left;
width: 20%;
text-align: center;
}
.heading-small {
margin-bottom: em(10);
}
ul {
padding-bottom: $gutter-half;
@include media(mobile) {
min-height: 50px;
padding-top: 10px;
}
}
li {
@include core-16;
}
b {
font-weight: bold;
text-transform: uppercase;
}
}
// 4. Images and icons
// ==========================================================================
.example-images img {
max-width: 100%;
vertical-align: top;
}
// 5. Data
// ==========================================================================
.data .bold-xlarge,
.data .bold-xxlarge {
line-height: 0.8;
}
.example .data p {
margin-bottom: 0;
}
// 6. Forms
// ==========================================================================
// 7. Buttons
// ==========================================================================
// Increase spacing under buttons in example boxes
.example-button .button {
margin-bottom: 15px;
}
// Remove top margin from "Creating buttons" example
.example-button .heading-small {
margin-top: 0;
}
// Make swatch wrapper full width for "Creating buttons" example
.example-button .swatch-wrapper {
width: 100%;
}
// Remove bottom padding to keep "Creating buttons" example
.example-button ul {
padding-bottom: 0;
}
// 9. Alpha beta banners
// ==========================================================================
// Alpha
.phase-banner-alpha {
@include phase-banner($state: alpha);
}
// Beta
.phase-banner-beta {
@include phase-banner($state: beta);
}

View File

@@ -1,50 +0,0 @@
// Global breadcrumb from Alphagov - static
// https://github.com/alphagov/static/blob/da8aeeaa749093eab30286d7fc9f965533b66f47/app/assets/stylesheets/helpers/_header.scss#L224
// Modified to use the new grid layout mixins
#global-breadcrumb {
@extend %grid-row;
ol {
@include grid-column(1);
padding-top: 0.75em;
padding-bottom: 0.75em;
li {
@include core-16;
float: left;
background-image: file-url("separator.png");
@include device-pixel-ratio() {
background-image: file-url("separator-2x.png");
background-size: 6px 11px;
}
background-position: 100% 50%;
background-repeat: no-repeat;
list-style: none;
margin-right: 0.5em;
margin-bottom: 0.4em;
margin-left: 0;
padding-right: 1em;
a {
color: $text-colour;
}
strong {
font-weight: normal;
}
&:last-child {
background-image: none;
margin-right: 0
}
}
}
}

View File

@@ -1,51 +0,0 @@
// Buttons
// ==========================================================================
.button {
@include button ($button-colour);
@include box-sizing (border-box);
margin: 0 $gutter-half $gutter-half 0;
padding: em(10) em(15) em(5) em(15);
vertical-align: top;
@include media (mobile) {
width: 100%;
}
}
// Fix unwanted button padding in Firefox
.button::-moz-focus-inner {
border: 0;
padding: 0;
}
.button:focus {
outline: 3px solid $focus-colour;
}
// Disabled buttons
.button[disabled="disabled"] {
background: $button-colour;
}
.button[disabled="disabled"]:focus {
outline: none;
}
// Start now buttons
.button-start,
.button-get-started {
@include bold-24;
background-image: file-url("icons/icon-pointer.png");
background-repeat: no-repeat;
background-position: 100% 50%;
padding: em(7) em(41) em(4) em(16);
@include device-pixel-ratio {
background-image: file-url("icons/icon-pointer-2x.png");
background-size: 30px 19px;
}
@include ie(6) {
background-image: file-url("icons/icon-pointer-2x.png");
}
}

View File

@@ -1,9 +0,0 @@
// Box with turquoise background and white text
// Used for transaction end pages, and Bank Holidays
.govuk-box-highlight {
margin: 1em 0 1em 0;
padding: 2em 0 1em 0;
color: $white;
background: $turquoise;
text-align: center;
}

View File

@@ -1,34 +0,0 @@
// Details
// ==========================================================================
details {
display: block;
summary {
display: inline-block;
color: $govuk-blue;
cursor: pointer;
position: relative;
margin-bottom: em(5);
&:hover {
color: $link-hover-colour;
}
&:focus {
outline: 3px solid $focus-colour;
}
}
// Underline only summary text (not the arrow)
.summary {
text-decoration: underline;
}
// Match fallback arrow spacing with -webkit default
.arrow {
margin-right: .35em;
font-style: normal;
}
}

View File

@@ -1,276 +0,0 @@
// Typography
// ==========================================================================
// Increase the base font size to 19px for the main content area
// Using the core-19 mixin from the govuk_toolkit _typography.scss file
main {
@include core-19;
-webkit-font-smoothing: antialiased;
}
// Core font sizes
.font-xxlarge {
@include core-80;
}
.font-xlarge {
@include core-48;
}
.font-large {
@include core-36;
}
.font-medium {
@include core-24;
}
.font-small {
@include core-19;
}
.font-xsmall {
@include core-16;
}
// Bold font sizes
.bold-xxlarge {
@include bold-80();
}
.bold-xlarge {
@include bold-48();
}
.bold-large {
@include bold-36();
}
.bold-medium {
@include bold-24();
}
.bold-small {
@include bold-19();
}
.bold-xsmall {
@include bold-16();
}
// Common heading sizes
// Using the bold-xx mixins from the govuk_toolkit _typography.scss file
// Spacing is set in em, using the px to em function in the elements _helpers.scss file
// Headings
.heading-xlarge {
@include bold-48();
margin-top: em(15, 32);
margin-bottom: em(30, 32);
@include media(tablet) {
margin-top: em(30, 48);
margin-bottom: em(60, 48);
}
.heading-secondary {
@include heading-27();
display: block;
color: $secondary-text-colour;
}
}
.heading-large {
@include bold-36();
margin-top: em(25, 24);
margin-bottom: em(10, 24);
@include media(tablet) {
margin-top: em(45, 36);
margin-bottom: em(20, 36);
}
.heading-secondary {
@include heading-24();
display: block;
color: $secondary-text-colour;
}
}
.heading-medium {
@include bold-24();
margin-top: em(25, 20);
margin-bottom: em(10, 20);
@include media(tablet) {
margin-top: em(45, 24);
margin-bottom: em(20, 24);
}
}
.heading-small {
@include bold-19();
margin-top: em(10, 16);
margin-bottom: em(5, 16);
@include media(tablet) {
margin-top: em(20, 19);
}
}
// Text
p {
margin-top: em(5, 16);
margin-bottom: em(20, 16);
@include media(tablet) {
margin-top: em(5);
margin-bottom: em(20);
}
}
// Lede, or intro text
.lede {
@include core-24;
}
// Set a max-width for text blocks
// Less than 75 characters per line of text
.text {
max-width: 30em;
}
.text-secondary {
color: $secondary-text-colour;
}
// Link styles
.link {
color: $link-colour;
text-decoration: underline;
}
.link:visited {
color: $link-visited-colour;
}
.link:hover {
color: $link-hover-colour;
}
.link:active {
color: $link-colour;
}
// Back link styles - with left pointing arrow
.link-back {
@include inline-block;
position: relative;
@include core-16;
margin-top: $gutter-half;
margin-bottom: $gutter-half;
padding-left: 14px;
color: $black;
&:link,
&:visited,
&:hover,
&:active {
color: $black;
}
text-decoration: none;
border-bottom: 1px solid $black;
// Back arrow - left pointing black arrow
&::before {
content: '';
display: block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-right: 6px solid #0b0c0c;
border-bottom: 5px solid transparent;
position: absolute;
left: 0;
top: 50%;
margin-top: -6px;
}
// Improve arrow shape in Firefox
@-moz-document url-prefix() {
&::before {
border-top: 5px dotted rgba(255, 0, 0, 0);
border-bottom: 5px dotted rgba(255, 0, 0, 0);
}
}
// Fallback
// IE8 doesn't support rgba and only supports the single colon syntax for :before
// IE7 doesn't support pseudo-elements, let's fallback to an image instead.
// Ref: http://caniuse.com/#search=%3Abefore, http://caniuse.com/#search=rgba
@include ie-lte(8) {
background: file-url("icon-arrow-left.png") no-repeat 0 4px;
}
}
// Code styles
.code {
color: black;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 14px;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
color: $black;
background-color: $highlight-colour;
border: 1px solid $border-colour;
padding: 4px 4px 2px 4px;
}
// Horizontal rule style
hr {
display: block;
background: $border-colour;
border: 0;
height: 1px;
margin-top: $gutter;
margin-bottom: $gutter;
padding: 0;
@include ie-lte(7) {
color: $border-colour;
}
}

View File

@@ -1,225 +0,0 @@
// Forms
// ==========================================================================
// Contents:
//
// 1. Helpers
// 2. Form wrappers
// 3. Form labels
// 4. Form hints
// 5. Form controls
// 6. Form control widths
// 1. Helpers
// ==========================================================================
// Fieldset is used to group more than one .form-group
fieldset {
@extend %contain-floats;
width: 100%;
}
// Fix left hand gap in IE7 and below
@include ie-lte(7) {
legend {
margin-left: -7px;
}
}
// Remove margin under textarea in Chrome and FF
textarea{
display: block;
}
// 2. Form wrappers
// ==========================================================================
// Form group is used to wrap label and input pairs
.form-group {
@extend %contain-floats;
@include box-sizing(border-box);
float: left;
width: 100%;
margin-bottom: $gutter-half;
@include media(tablet) {
margin-bottom: $gutter;
}
}
// Form group related is used to reduce the space between label and input pairs
.form-group-related {
margin-bottom: 10px;
@include media(tablet) {
margin-bottom: 20px;
}
}
// Form group compound is used to reduce the space between label and input pairs
.form-group-compound {
margin-bottom: 10px;
}
// 3. Form labels
// ==========================================================================
// Form labels, or for legends styled to look like labels
// TODO: Amend so there is only one label style
.form-label,
.form-label-bold {
display: block;
color: $text-colour;
}
.form-label {
@include core-19;
}
.form-label-bold {
@include bold-19;
}
// Add spacing under spans within labels
legend {
.form-label,
.form-label-bold {
padding-bottom: 7px;
}
}
// Remove spacing when error messages are shown
// TODO: Move into /forms/_form-validation.scss
.error legend {
.form-label,
.form-label-bold {
padding-bottom: 0;
}
}
// Used for the 'or' in between block label options
.form-block {
@extend %contain-floats;
float: left;
width: 100%;
margin-top: -5px;
margin-bottom: 5px;
@include media(tablet) {
margin-top: 0;
margin-bottom: 10px;
}
}
// 4. Form hints
// ==========================================================================
// Form hints and example text are light grey and sit above a form control
.form-hint {
@include core-19;
display: block;
color: $secondary-text-colour;
font-weight: normal;
margin-bottom: 5px;
}
// 5. Form controls
// ==========================================================================
// By default, form controls are 50% width for desktop,
// and 100% width for mobile
.form-control {
@include box-sizing(border-box);
@include core-19;
width: 100%;
padding: 4px;
background-color: $white;
border: 2px solid $grey-1;
// TODO: Remove 50% width set for tablet and up
// !! BREAKING CHANGE !!
@include media(tablet) {
width: 50%;
}
}
// Radio buttons
.form-radio {
display: block;
margin: 10px 0;
input {
vertical-align: middle;
margin: -4px 5px 0 0;
}
}
// Checkboxes
.form-checkbox {
display: block;
margin: $gutter-half 0;
input {
vertical-align: middle;
margin: -2px 5px 0 0;
}
}
// 6. Form control widths
// ==========================================================================
// TODO: Update these
// Form control widths
.form-control-3-4 {
width: 100%;
@include media(tablet) {
width: 75%;
}
}
.form-control-2-3 {
width: 100%;
@include media(tablet) {
width: 66.66%;
}
}
.form-control-1-2 {
width: 100%;
@include media(tablet) {
width: 50%;
}
}
.form-control-1-3 {
width: 100%;
@include media(tablet) {
width: 33.33%;
}
}
.form-control-1-4 {
width: 100%;
@include media(tablet) {
width: 25%;
}
}
.form-control-1-8 {
width: 100%;
@include media(tablet) {
width: 12.5%;
}
}

View File

@@ -1,44 +0,0 @@
// Helpers
// ==========================================================================
// Path to assets for use with file-url() is not already defined
@if ($path == false) {
$path: "/public/images/";
}
// Return ems from a pixel value
// This assumes a base of 19px
@function em($px, $base: 19) {
@return ($px / $base) + em;
}
// Want to see how the grid works?
// add this class to the body to see how grid padding is set
.example-highlight-grid {
.grid-row {
background: $grey-2;
}
.column-highlight {
background: $grey-3;
width: 100%;
}
}
// Hide, but not for screenreaders
.visuallyhidden {
position: absolute;
overflow: hidden;
clip: rect(0 0 0 0);
height: 1px;
width: 1px;
margin: -1px;
padding: 0;
border: 0;
}
// Hide, only when JavaScript is enabled
.js-enabled .js-hidden {
display: none;
}

View File

@@ -1,244 +0,0 @@
// GOV.UK icons
.icon {
background-position: 0 0;
background-repeat: no-repeat;
}
.icon-calendar {
width: 27px;
height: 27px;
background-image: file-url("icons/icon-calendar.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-calendar-2x.png");
background-size: 100%;
}
}
.icon-download {
width: 30px;
height: 39px;
background-image: file-url("icons/icon-file-download.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-file-download-2x.png");
background-size: 100%;
}
}
.icon-important {
width: 34px;
height: 34px;
background-image: file-url("icons/icon-important.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-important-2x.png");
background-size: 100%;
}
}
.icon-information {
width: 27px;
height: 27px;
background-image: file-url("icons/icon-information.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-information-2x.png");
background-size: 100%;
}
}
.icon-locator {
width: 26px;
height: 36px;
background-image: file-url("icons/icon-locator.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-locator-2x.png");
background-size: 100%;
}
}
.icon-search {
width: 30px;
height: 22px;
background-color: $black;
background-image: file-url("icons/icon-search.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-search-2x.png");
background-size: 100%;
}
}
// GOV.UK arrow icons
.icon-pointer {
width: 30px;
height: 19px;
background-color: $black;
background-image: file-url("icons/icon-pointer.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-pointer-2x.png");
background-size: 100%;
}
}
.icon-pointer-black {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-pointer-black.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-pointer-black-2x.png");
background-size: 100%;
}
}
// GOV.UK external link icons
// TODO (Are these provided by the template?)
// GOV.UK step icons
.icon-step-1 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-1.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-1-2x.png");
background-size: 100%;
}
}
.icon-step-2 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-2.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-2-2x.png");
background-size: 100%;
}
}
.icon-step-3 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-3.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-3-2x.png");
background-size: 100%;
}
}
.icon-step-4 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-4.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-4-2x.png");
background-size: 100%;
}
}
.icon-step-5 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-5.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-5-2x.png");
background-size: 100%;
}
}
.icon-step-6 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-6.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-6-2x.png");
background-size: 100%;
}
}
.icon-step-7 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-7.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-7-2x.png");
background-size: 100%;
}
}
.icon-step-8 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-8.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-8-2x.png");
background-size: 100%;
}
}
.icon-step-9 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-9.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-9-2x.png");
background-size: 100%;
}
}
.icon-step-10 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-10.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-10-2x.png");
background-size: 100%;
}
}
.icon-step-11 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-11.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-11-2x.png");
background-size: 100%;
}
}
.icon-step-12 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-12.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-12-2x.png");
background-size: 100%;
}
}
.icon-step-13 {
width: 23px;
height: 23px;
background-image: file-url("icons/icon-steps/icon-step-13.png");
@include device-pixel-ratio() {
background-image: file-url("icons/icon-steps/icon-step-13-2x.png");
background-size: 100%;
}
}

View File

@@ -1,63 +0,0 @@
// Layout
// ==========================================================================
// Content
// ==========================================================================
// Content wraps the entire site content block
#content {
@extend %site-width-container;
@extend %contain-floats;
padding-bottom: $gutter;
@include media(desktop) {
padding-bottom: $gutter*3;
}
}
// Phase banner
// ==========================================================================
.phase-banner {
@include phase-banner(alpha);
}
// Grid layout
// ==========================================================================
// Usage:
// For two equal columns
// <div class="grid-row">
// <div class="column-half">
//
// </div>
// <div class="column-half">
//
// </div>
// </div>
// Use .grid-row to define a row for grid columns to sit in
.grid-row {
@extend %grid-row;
}
// Use .grid-column to create a grid column with 15px gutter
// By default grid columns break to become full width at tablet size
.column-quarter {
@include grid-column(1/4);
}
.column-half {
@include grid-column(1/2);
}
.column-third {
@include grid-column(1/3);
}
.column-two-thirds {
@include grid-column(2/3);
}

View File

@@ -1,36 +0,0 @@
// Lists
// ==========================================================================
ul,
ol {
list-style-type: none;
padding: 0;
}
// Bulleted lists
.list-bullet {
list-style-type: disc;
padding-left: 20px;
}
// Numbered lists
.list-number {
list-style-type: decimal;
padding-left: 20px;
@include ie-lte(7) {
padding-left: 28px;
}
}
.list-bullet,
.list-number {
margin-top: 5px;
margin-bottom: 20px;
}
.list-bullet li,
.list-number li {
margin-bottom: 5px;
}

View File

@@ -1,31 +0,0 @@
// Panels
// ==========================================================================
// Indented panels with a grey left hand border
.panel-indent {
@extend %contain-floats;
clear: both;
border-left: 5px solid $border-colour;
padding: em(15,19);
margin-bottom: em(15,19);
:first-child {
margin-top: 0;
}
:only-child,
:last-child {
margin-bottom: 0;
}
}
.panel-indent-info {
border-left-width: 10px;
}
// Indented panels within form groups
.form-group .panel-indent {
padding-bottom: 0;
}

View File

@@ -1,33 +0,0 @@
// Reset
// ==========================================================================
// flatten all browser defaults and styles inherited from gov.uk template
/* Borrowed from http://meyerweb.com/eric/tools/css/reset/ */
div, span,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark {
border: none;
margin: 0;
padding: 0;
}
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
input, textarea,
table, caption, tbody, tfoot, thead, tr, th, td {
font-size: inherit;
font-family: inherit;
line-height: inherit;
font-weight: normal;
}

View File

@@ -1,32 +0,0 @@
// Tables
// ==========================================================================
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
th,
td {
@include core-16;
padding: em(12, 16) em(20, 16) em(9, 16) 0;
text-align: left;
color: $black;
border-bottom: 1px solid $border-colour;
}
th {
font-weight: 700;
// Right align headings for numeric content
&.numeric {
text-align: right;
}
}
// Use tabular numbers for numeric table cells
td.numeric {
@include core-16($tabular-numbers: true);
text-align: right;
}
}

View File

@@ -1,70 +0,0 @@
// Large hit area
// Radio buttons & checkboxes
// By default, block labels stack vertically
.block-label {
display: block;
float: none;
clear: left;
position: relative;
background: $panel-colour;
border: 1px solid $panel-colour;
padding: (18px $gutter $gutter-half $gutter*1.8);
margin-bottom: 10px;
cursor: pointer; // Encourage clicking on block labels
@include media(tablet) {
float: left;
// width: 25%; - Test : check that text within labels will wrap
}
// Absolutely position inputs within label, to allow text to wrap
input {
position: absolute;
top: 15px;
left: $gutter-half;
cursor: pointer;
margin: 0;
width: 29px;
height: 29px;
@include ie(8) {
top: 12px;
}
}
// Change border on hover
&:hover {
border-color: $black;
}
}
.block-label:last-child {
margin-bottom: 0;
}
// To stack horizontally, use .inline on parent, to sit block labels next to each other
.inline .block-label {
clear: none;
margin-right: 10px;
}
// Selected and focused states
// Add selected state
.js-enabled label.selected {
background: $white;
border-color: $black;
}
// Add focus to block labels
.js-enabled label.focused {
outline: 3px solid $focus-colour;
}
// Remove focus from radio/checkboxes
.js-enabled .focused input:focus {
outline: none;
}

View File

@@ -1,38 +0,0 @@
// Date pattern
// Hide the 'spinner' for webkit
// and also for Firefox
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
}
.form-date {
.form-group {
float: left;
width: 50px;
margin-right: 20px;
margin-bottom: 0;
clear: none;
label {
display: block;
margin-bottom: 5px;
}
input {
width: 100%;
}
}
.form-group-year {
width: 70px;
}
}

View File

@@ -1,104 +0,0 @@
// Form validation
// ==========================================================================
// Using the classname .error as it's shorter than .validation and easier to type!
.error {
// Ensure the .error class is applied to .form-group, otherwide box-sizing(border-box) will need to be used
// @include box-sizing(border-box);
margin-right: 15px;
// Error messages should be red and bold
.error-message {
color: $error-colour;
font-weight: bold;
}
// Form inputs should have a red border
.form-control {
border: 4px solid $error-colour;
}
.form-hint {
margin-bottom: 0;
}
}
.error,
.error-summary {
// Add a red border to the left of the field
border-left: 4px solid $error-colour;
padding-left: 10px;
@include media(tablet) {
border-left: 5px solid $error-colour;
padding-left: $gutter-half;
}
}
.error-message {
@include core-19;
display: block;
clear: both;
margin: 0;
padding: 5px 0 7px 0;
}
// Summary of multiple error messages
.error-summary {
// Error summary has a border on all sides
border: 4px solid $error-colour;
margin-top: $gutter-half;
margin-bottom: $gutter-half;
padding: $gutter-half 10px;
@include media(tablet) {
border: 5px solid $error-colour;
margin-top: $gutter;
margin-bottom: $gutter;
padding: 20px $gutter-half $gutter-half $gutter-half;
}
@include ie-lte(6) {
zoom: 1;
}
// Use the GOV.UK outline focus style
&:focus {
outline: 3px solid $focus-colour;
}
.error-summary-heading {
margin-top: 0;
}
p {
margin-bottom: 10px;
}
.error-summary-list {
padding-left: 0;
li {
@include media(tablet) {
margin-bottom: 5px;
}
}
a {
color: $error-colour;
font-weight: bold;
text-decoration: underline;
}
}
}

View File

@@ -1,5 +0,0 @@
$is-ie: true;
$ie-version: 6;
$mobile-ie6: false;
@import "main";

View File

@@ -1,4 +0,0 @@
$is-ie: true;
$ie-version: 7;
@import "main";

View File

@@ -1,4 +0,0 @@
$is-ie: true;
$ie-version: 8;
@import "main";

View File

@@ -1,28 +0,0 @@
// GOV.UK front end toolkit
// Sass mixins and variables
// https://github.com/alphagov/govuk_frontend_toolkit/tree/master/stylesheets
@import "../../govuk_frontend_toolkit/stylesheets/design-patterns/alpha-beta";
@import "../../govuk_frontend_toolkit/stylesheets/design-patterns/buttons";
// GOV.UK elements
@import "elements/helpers";
@import "elements/reset";
@import "elements/elements-typography";
@import "elements/layout";
@import "elements/forms";
@import "elements/forms/form-block-labels";
@import "elements/forms/form-date";
@import "elements/forms/form-validation";
@import "elements/tables";
@import "elements/lists";
@import "elements/details";
@import "elements/panels";
@import "elements/buttons";
@import "elements/icons";
@import "elements/components";
@import "elements/breadcrumb";

View File

@@ -1,15 +1,11 @@
/* govuk_frontend_toolkit includes */
@import "../../govuk_frontend_toolkit/stylesheets/colours";
@import "../../govuk_frontend_toolkit/stylesheets/conditionals";
@import "../../govuk_frontend_toolkit/stylesheets/css3";
@import "../../govuk_frontend_toolkit/stylesheets/device-pixels";
@import "../../govuk_frontend_toolkit/stylesheets/typography";
@import "../../govuk_frontend_toolkit/stylesheets/grid_layout";
@import "../../govuk_frontend_toolkit/stylesheets/design-patterns/_buttons";
// Edited version of govuk_elements repo
// https://github.com/alphagov/govuk_elements
@import "../govuk_elements/main";
@import "../govuk_frontend_toolkit/stylesheets/colours";
@import "../govuk_frontend_toolkit/stylesheets/conditionals";
@import "../govuk_frontend_toolkit/stylesheets/css3";
@import "../govuk_frontend_toolkit/stylesheets/device-pixels";
@import "../govuk_frontend_toolkit/stylesheets/typography";
@import "../govuk_frontend_toolkit/stylesheets/grid_layout";
@import "../govuk_frontend_toolkit/stylesheets/design-patterns/_buttons";
/* local styleguide includes */
@import "styleguide/colours";
@@ -20,8 +16,3 @@
@import "accessibility";
@import "header";
@import "footer";
// Extra CSS for this application
@import "../app";

View File

@@ -7,31 +7,32 @@
@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";
// Edited version of govuk_template repo
// https://github.com/alphagov/govuk_template
@import "govuk_template/govuk-template";
@import "govuk_template/govuk-template-ie6";
@import "govuk_template/govuk-template-ie7";
@import "govuk_template/govuk-template-ie8";
@import "govuk_template/govuk-template-print";
// Edited version of govuk_elements repo
// https://github.com/alphagov/govuk_elements
@import "govuk_elements/elements/reset";
@import "govuk_elements/elements/buttons";
@import "govuk_elements/elements/details";
@import "govuk_elements/elements/elements-typography";
@import "govuk_elements/elements/forms";
@import "govuk_elements/elements/helpers";
@import "govuk_elements/elements/icons";
@import "govuk_elements/elements/layout";
@import "govuk_elements/elements/lists";
@import "govuk_elements/elements/panels";
@import "govuk_elements/elements/tables";
@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-block-labels";
@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";
// Extra CSS for this application
@import "components/template-picker";
@import "components/placeholder";
@import "components/sms-message";
@import "components/submit-form";
@import "components/table";
// TODO: break this up
@import "app";

View File

@@ -3,4 +3,4 @@ from flask import Blueprint
main = Blueprint('main', __name__)
from app.main.views import index, sign_in, register, two_factor, verify
from app.main.views import index, sign_in, register, two_factor, verify, sms

View File

@@ -6,126 +6,116 @@ from app.main import main
@main.route('/')
def index():
return render_template('signedout.html')
return render_template('views/signedout.html')
@main.route("/govuk")
def govuk():
return render_template('govuk_template.html')
return render_template('views/govuk_template.html')
@main.route("/register-from-invite")
def registerfrominvite():
return render_template('register-from-invite.html')
return render_template('views/register-from-invite.html')
@main.route("/verify-mobile")
def verifymobile():
return render_template('verify-mobile.html')
return render_template('views/verify-mobile.html')
@main.route("/text-not-received-2")
def textnotreceived2():
return render_template('text-not-received-2.html')
return render_template('views/text-not-received-2.html')
@main.route("/dashboard")
@login_required
def dashboard():
return render_template('dashboard.html')
return render_template('views/dashboard.html')
@main.route("/add-service")
@login_required
def addservice():
return render_template('add-service.html')
@main.route("/send-sms")
def sendsms():
return render_template('send-sms.html')
@main.route("/check-sms")
def checksms():
return render_template('check-sms.html')
return render_template('views/add-service.html')
@main.route("/email-not-received")
def emailnotreceived():
return render_template('email-not-received.html')
return render_template('views/email-not-received.html')
@main.route("/text-not-received")
def textnotreceived():
return render_template('text-not-received.html')
return render_template('views/text-not-received.html')
@main.route("/send-email")
def sendemail():
return render_template('send-email.html')
return render_template('views/send-email.html')
@main.route("/check-email")
def checkemail():
return render_template('check-email.html')
return render_template('views/check-email.html')
@main.route("/jobs")
def showjobs():
return render_template('jobs.html')
return render_template('views/jobs.html')
@main.route("/jobs/job")
def showjob():
return render_template('job.html')
return render_template('views/job.html')
@main.route("/jobs/job/notification")
def shownotification():
return render_template('notification.html')
return render_template('views/notification.html')
@main.route("/forgot-password")
def forgotpassword():
return render_template('forgot-password.html')
return render_template('views/forgot-password.html')
@main.route("/new-password")
def newpassword():
return render_template('new-password.html')
return render_template('views/new-password.html')
@main.route("/user-profile")
def userprofile():
return render_template('user-profile.html')
return render_template('views/user-profile.html')
@main.route("/manage-users")
def manageusers():
return render_template('manage-users.html')
return render_template('views/manage-users.html')
@main.route("/service-settings")
def servicesettings():
return render_template('service-settings.html')
return render_template('views/service-settings.html')
@main.route("/api-keys")
def apikeys():
return render_template('api-keys.html')
return render_template('views/api-keys.html')
@main.route("/verification-not-received")
def verificationnotreceived():
return render_template('verification-not-received.html')
return render_template('views/verification-not-received.html')
@main.route("/manage-templates")
def managetemplates():
return render_template('manage-templates.html')
return render_template('views/manage-templates.html')
@main.route("/edit-template")
def edittemplate():
return render_template('edit-template.html')
return render_template('views/edit-template.html')

View File

@@ -14,7 +14,7 @@ from app.models import User
@main.route("/register", methods=['GET'])
def render_register():
return render_template('register.html', form=RegisterUserForm())
return render_template('views/register.html', form=RegisterUserForm())
@main.route('/register', methods=['POST'])

View File

@@ -11,7 +11,7 @@ from app.main.views import send_sms_code
@main.route("/sign-in", methods=(['GET']))
def render_sign_in():
return render_template('signin.html', form=LoginForm())
return render_template('views/signin.html', form=LoginForm())
@main.route('/sign-in', methods=(['POST']))

66
app/main/views/sms.py Normal file
View File

@@ -0,0 +1,66 @@
from flask import request, render_template, redirect, url_for
from flask_login import login_required
from app.main import main
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
"""
},
]
@main.route("/sms/send", methods=['GET', 'POST'])
def sendsms():
if request.method == 'GET':
return render_template(
'views/send-sms.html',
message_templates=message_templates
)
elif request.method == 'POST':
return redirect(url_for('.checksms'))
@main.route("/sms/check", methods=['GET', 'POST'])
def checksms():
recipients = [
{'phone': "+44 7700 900989", 'registration number': 'LC12 BFL', 'date': '24 December 2015'},
{'phone': "+44 7700 900479", 'registration number': 'DU04 AOM', 'date': '25 December 2015'},
{'phone': "+44 7700 900964", 'registration number': 'M91 MJB', 'date': '26 December 2015'},
{'phone': "+44 7700 900703", 'registration number': 'Y249 NPU', 'date': '31 December 2015'},
{'phone': "+44 7700 900730", 'registration number': 'LG55 UGB', 'date': '1 January 2016'},
{'phone': "+44 7700 900989", 'registration number': 'LC12 BFL', 'date': '24 December 2015'},
{'phone': "+44 7700 900479", 'registration number': 'DU04 AOM', 'date': '25 December 2015'},
{'phone': "+44 7700 900964", 'registration number': 'M91 MJB', 'date': '26 December 2015'},
{'phone': "+44 7700 900703", 'registration number': 'Y249 NPU', 'date': '31 December 2015'},
{'phone': "+44 7700 900730", 'registration number': 'LG55 UGB', 'date': '1 January 2016'},
]
number_of_recipients = len(recipients)
too_many_recipients_to_display = number_of_recipients > 7
if request.method == 'GET':
return render_template(
'views/check-sms.html',
number_of_recipients=number_of_recipients,
recipients={
"first_three": recipients[:3] if too_many_recipients_to_display else [],
"last_three": recipients[number_of_recipients - 3:] if too_many_recipients_to_display else [],
"all": recipients if not too_many_recipients_to_display else []
},
message_template=message_templates[0]['body']
)
elif request.method == 'POST':
return redirect(url_for('.showjob'))

View File

@@ -8,7 +8,7 @@ from app.main.forms import TwoFactorForm
@main.route("/two-factor", methods=['GET'])
def render_two_factor():
return render_template('two-factor.html', form=TwoFactorForm())
return render_template('views/two-factor.html', form=TwoFactorForm())
@main.route('/two-factor', methods=['POST'])

View File

@@ -8,7 +8,7 @@ from app.main.forms import VerifyForm
@main.route('/verify', methods=['GET'])
def render_verify():
return render_template('verify.html', form=VerifyForm())
return render_template('views/verify.html', form=VerifyForm())
@main.route('/verify', methods=['POST'])

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,10 @@
{% extends "govuk_template.html" %}
{% block head %}
{% assets "css_all" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" />
{% endassets %}
{% endblock %}
{% block page_title %}
GOV.UK notifications admin
@@ -12,9 +17,9 @@ GOV.UK notifications admin
{% block inside_header %}
<div class="phase-banner-beta">
<strong class="phase-tag">BETA</strong>
</div>
{% endblock %}
@@ -27,4 +32,3 @@ GOV.UK notifications admin
{% else %}
{% set homepage_url = url_for('main.dashboard') %}
{% endif %}

View File

@@ -1,21 +0,0 @@
{% extends "admin_template.html" %}
{% block page_title %}
GOV.UK Notify | Send text messages
{% endblock %}
{% block content %}
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Send text messages</h1>
<p>This page will be where we check the text messages we're about to send</p>
<p>
<a class="button" href="dashboard" role="button">Send text messages</a>
</p>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,3 @@
{% macro placeholder(variable) %}
<span class='placeholder'>{{variable}}</span>
{% endmacro %}

View File

@@ -0,0 +1,12 @@
{% macro sms_message(body, recipient) %}
{% if recipient %}
<p class="sms-message-recipient">
{{ recipient }}
</p>
{% endif %}
<div class="sms-message">
<div class="sms-message-wrapper">
{{ body|placeholders }}
</div>
</div>
{% endmacro %}

View File

@@ -0,0 +1,11 @@
{% macro submit_form(button_text, back_link) %}
<div class="submit-form">
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="submit" class="button" value="{{ button_text }}" />
{% if back_link %}
<a class="submit-form-back-link" role="button" href="{{ back_link }}">Back</a>
{% endif %}
</form>
</div>
{% endmacro %}

View File

@@ -0,0 +1,39 @@
{% macro table(items, caption='', field_headings='', field_headings_visible=True) -%}
<table class="table">
<caption class="heading-medium table-heading">
{{ caption }}
</caption>
<thead class="table-field-headings{% if field_headings_visible %}-visible{% endif %}">
<tr>
{% for field_heading in field_headings %}
<th scope="col" class="table-field-heading{% if loop.first %}-first{% endif %}">
{% if field_headings_visible %}
{{ field_heading }}
{% else %}
<span class="visuallyhidden">{{ field_heading }}</span>
{% endif %}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% if items %}
{% for item in items %}
<tr class="table-row">
{{ caller(item) }}
</tr>
{% endfor %}
{% else %}
<p class="table-no-content">
{{ empty_message }}
</p>
{% endif %}
</tbody>
</table>
{%- endmacro %}
{% macro field(first=False, wide=False, action=False) -%}
<td class="table-field{% if first %}-first{% endif %}{% if first and wide %}-wider{% endif %}{% if action %}-with-action{% endif %}">
<span>{{ caller() }}</span>
</td>
{%- endmacro %}

View File

@@ -1,26 +0,0 @@
{% extends "admin_template.html" %}
{% block page_title %}
GOV.UK Notify | Dashboard
{% endblock %}
{% block content %}
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Dashboard</h1>
<ul>
<li><a href="send-sms">Send text messages</a></li>
<li><a href="send-email">Send email messages</a></li>
<li><a href="jobs">View notifications activity</a></li>
<li><a href="user-profile">User profile</a></li>
<li><a href="manage-users">Manage users</a></li>
<li><a href="manage-templates">Manage templates</a></li>
<li><a href="service-settings">Service settings</a></li>
<li><a href="api-keys">API keys and documentation</a></li>
</ul>
</div>
</div>
{% endblock %}

View File

@@ -1,21 +0,0 @@
{% extends "admin_template.html" %}
{% block page_title %}
GOV.UK Notify | Send text messages
{% endblock %}
{% block content %}
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Send text messages</h1>
<p>This page will be where we construct text messages</p>
<p>
<a class="button" href="check-sms" role="button">Continue</a>
</p>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,67 @@
{% extends "admin_template.html" %}
{% from "components/sms-message.html" import sms_message %}
{% from "components/table.html" import table, field %}
{% from "components/placeholder.html" import placeholder %}
{% from "components/submit-form.html" import submit_form %}
{% block page_title %}
GOV.UK Notify | Send text messages
{% endblock %}
{% block content %}
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Send text messages</h1>
<h2 class="heading-medium">Check and confirm</h2>
{{ submit_form(
"Send {} text messages".format(number_of_recipients),
url_for(".sendsms")
) }}
<h3 class="heading-small">First 3 messages</h2>
{% if recipients.first_three and recipients.last_three %}
{% for recipient in recipients.first_three %}
{{ sms_message(
message_template|replace_placeholders(recipient),
"{}".format(recipient['phone'])
) }}
{% endfor %}
<h3 class="heading-small">Last 3 messages</h2>
{% for recipient in recipients.last_three %}
{{ sms_message(
message_template|replace_placeholders(recipient),
"{}".format(recipient['phone'])
) }}
{% endfor %}
{% else %}
{% for recipient in recipients.all %}
{{ sms_message(
message_template|replace_placeholders(recipient),
"{}".format(recipient['phone'])
) }}
{% endfor %}
{% endif %}
<p>
<a href="#">See all</a>
</p>
{{ submit_form(
"Send {} text messages".format(number_of_recipients),
url_for(".sendsms")
) }}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,26 @@
{% extends "admin_template.html" %}
{% block page_title %}
GOV.UK Notify | Dashboard
{% endblock %}
{% block content %}
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Dashboard</h1>
<ul>
<li><a href="{{ url_for('.sendsms') }}">Send text messages</a></li>
<li><a href="{{ url_for('.sendemail') }}">Send email messages</a></li>
<li><a href="{{ url_for('.showjobs') }}">View notifications activity</a></li>
<li><a href="{{ url_for('.userprofile') }}">User profile</a></li>
<li><a href="{{ url_for('.manageusers') }}">Manage users</a></li>
<li><a href="{{ url_for('.managetemplates')}}">Manage templates</a></li>
<li><a href="{{ url_for('.servicesettings') }}">Service settings</a></li>
<li><a href="{{ url_for('.apikeys') }}">API keys and documentation</a></li>
</ul>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,53 @@
{% extends "admin_template.html" %}
{% from "components/sms-message.html" import sms_message %}
{% block page_title %}
GOV.UK Notify | Send text messages
{% endblock %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
<div class="grid-row">
<div class="column-two-thirds">
<h1 class="heading-xlarge">Send text messages</h1>
<h2 class="heading-medium">1. Choose text message template</h2>
{% for template in message_templates %}
<div class="template-picker-option">
<div class="template-picker-option-radio">
<label class="block-label" for="template-{{loop.index}}">
{{ template.name }}
<input type="radio" name="template" id="template-{{loop.index}}" value="{{ template.name }}" />
</label>
</div>
{{ sms_message(template.body) }}
</div>
{% endfor %}
<p>
or <a href="{{ url_for(".managetemplates") }}">create a new template</a>
</p>
<h2 class="heading-medium">2. Add recipients</h2>
<p>
Upload a CSV file to add your recipients details.
</p>
<p>
You can also <a href="#">download an example CSV</a>.
</p>
<p>
<input type="file" />
</p>
<p>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="submit" class="button" value="Continue" />
</p>
</div>
</div>
</form>
{% endblock %}