Merge branch 'master' into letters-from-a-service

This commit is contained in:
Leo Hemsted
2017-04-11 17:11:51 +01:00
21 changed files with 141 additions and 149 deletions

View File

@@ -2,8 +2,6 @@ $(() => $("time.timeago").timeago());
$(() => GOVUK.modules.start());
$(() => new GOVUK.SelectionButtons('.block-label input, .sms-message-option input'));
$(() => $('.error-message').eq(0).parent('label').next('input').trigger('focus'));
$(() => $('.banner-dangerous').eq(0).trigger('focus'));

View File

@@ -5,54 +5,57 @@
let states = {
'initial': Hogan.compile(`
<div class="radio-select-column">
<label class="block-label js-block-label" for="{{name}}-0">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value=""> Now
</label>
<div class="multiple-choice js-multiple-choice">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
<label class="block-label js-block-label" for="{{name}}-0">Now</label>
</div>
</div>
<div class="radio-select-column">
{{#categories}}
<input type='button' class='button tertiary-button js-category-button' value='{{.}}' />
<input type='button' class='js-category-button' value='{{.}}' />
{{/categories}}
</div>
`),
'choose': Hogan.compile(`
<div class="radio-select-column">
<label class="block-label js-block-label" for="{{name}}-0">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="" class="js-initial-option"> Now
</label>
<div class="multiple-choice js-multiple-choice js-initial-option">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
<label for="{{name}}-0">Now</label>
</div>
</div>
<div class="radio-select-column">
{{#choices}}
<label class="block-label js-block-label" for="{{id}}">
<input type="radio" value="{{value}}" id="{{id}}" name="{{name}}" class="js-option" />
{{label}}
</label>
<div class="multiple-choice js-multiple-choice js-option">
<input type="radio" value="{{value}}" id="{{id}}" name="{{name}}" />
<label for="{{id}}">{{label}}</label>
</div>
{{/choices}}
</div>
`),
'chosen': Hogan.compile(`
<div class="radio-select-column">
<label class="block-label js-block-label" for="{{name}}-0">
<input id="{{name}}-0" name="{{name}}" type="radio" value="" class="js-initial-option"> Now
</label>
<div class="multiple-choice js-multiple-choice js-initial-option">
<input id="{{name}}-0" name="{{name}}" type="radio" value="">
<label for="{{name}}-0">Now</label>
</div>
</div>
<div class="radio-select-column">
{{#choices}}
<label class="block-label js-block-label" for="{{id}}">
<div class="multiple-choice js-multiple-choice">
<input checked="checked" type="radio" value="{{value}}" id="{{id}}" name="{{name}}" />
{{label}}
</label>
<label for="{{id}}">{{label}}</label>
</div>
{{/choices}}
</div>
<div class="radio-select-column">
<input type='button' class='button tertiary-button js-reset-button' value='Choose a different time' />
<input type='button' class='category-link js-reset-button' value='Choose a different time' />
</div>
`)
};
let focusSelected = function() {
setTimeout(
() => $('[type=radio]:checked').parent('label').blur().trigger('focus').addClass('selected'),
() => $('[type=radio]:checked').next('label').blur().trigger('focus').addClass('selected'),
10
);
};
@@ -62,13 +65,16 @@
this.start = function(component) {
let $component = $(component);
let render = (state, data) => $component.html(states[state].render(data));
let render = (state, data) => {
$component.html(states[state].render(data));
new GOVUK.SelectionButtons('.block-label input');
};
let choices = $('label', $component).toArray().map(function(element) {
let $element = $(element);
return {
'id': $element.attr('for'),
'label': $.trim($element.text()),
'value': $element.find('input').attr('value')
'value': $element.prev('input').attr('value')
};
});
let categories = $component.data('categories').split(',');
@@ -95,7 +101,7 @@
if (!event.pageX) return true;
event.preventDefault();
let value = $(this).attr('value');
let value = $('input', this).attr('value');
render('chosen', {
'choices': choices.filter(
element => element.value == value

View File

@@ -18,6 +18,10 @@
@include grid-column(1/8);
}
.column-five-eighths {
@include grid-column(5/8);
}
.column-seven-eighths {
@include grid-column(7/8);
}

View File

@@ -46,8 +46,7 @@
}
.beta-badge {
@include phase-tag(beta);
background: $govuk-blue;
@include phase-tag();
margin: 10px 0 0 0;
}
@@ -151,22 +150,10 @@ td {
margin-bottom: 5px;
}
a[rel='external'] {
@include external-link-default;
@include external-link-16;
@include media(tablet) {
@include external-link-19;
}
}
.hint {
color: $secondary-text-colour;
}
.button {
padding: 0.3em 0.6em 0.2em 0.6em;
}
.list-bullet {
.list-bullet {
@@ -256,10 +243,16 @@ details .arrow {
margin-top: 5px;
}
.block-label input[disabled] {
opacity: 0.5;
}
#content.override-elements-content {
padding-bottom: 0;
}
.multiple-choice input:disabled+label {
opacity: 1;
color: $secondary-text-colour;
cursor: default;
}
.multiple-choice input:disabled {
opacity: 0.5;
}

View File

@@ -5,33 +5,38 @@
display: inline-block;
vertical-align: top;
.block-label {
.multiple-choice {
margin-right: 5px;
padding-right: $gutter - 10px;
padding-right: 10px;
padding-left: 54px - 10px;
}
}
.tertiary-button {
.js-reset-button,
.js-category-button {
background: none;
text-decoration: underline;
color: $link-colour;
//font-weight: bold;
border: none;
display: inline-block;
vertical-align: top;
width: auto;
padding: 20px $gutter-half 15px $gutter-half;
padding: 7px 20px 7px 10px;
margin-right: 5px;
}
.js-enabled & {
height: 60px;
overflow: visible;
.block-label {
.multiple-choice {
display: none;
}
.js-block-label {
display: inline-block;
.js-multiple-choice {
display: block;
}
}

View File

@@ -2,7 +2,7 @@
.sms-message-wrapper {
width: 100%;
max-width: 450px;
max-width: 464px;
box-sizing: border-box;
padding: $gutter-half $gutter-half $gutter-half $gutter-half;
background: $panel-colour;

View File

@@ -24,7 +24,7 @@ $path: '/static/images/';
@import 'elements/elements-typography';
@import 'elements/forms';
@import 'elements/forms/form-validation';
@import 'elements/forms/form-block-labels';
@import 'elements/forms/form-multiple-choice';
@import 'elements/forms/form-validation';
@import 'elements/icons';
@import 'elements/layout';

View File

@@ -30,12 +30,12 @@
.edit-template-link-letter-address {
@extend %edit-template-link;
top: 16.5%; // align bottom edge to bottom of address
top: 14.65%; // align bottom edge to bottom of address
left: -5px;
}
.edit-template-link-letter-body {
@extend %edit-template-link;
top: 33.3%; // aligns to top of subject
top: 38.5%; // aligns to top of subject
left: -5px;
}

View File

@@ -2,37 +2,18 @@ import uuid
import botocore
from boto3 import resource
from flask import current_app
from notifications_utils.s3 import s3upload as utils_s3upload
FILE_LOCATION_STRUCTURE = 'service-{}-notify/{}.csv'
def s3upload(service_id, filedata, region):
s3 = resource('s3')
bucket_name = current_app.config['CSV_UPLOAD_BUCKET_NAME']
contents = filedata['data']
exists = True
try:
s3.meta.client.head_bucket(
Bucket=bucket_name)
except botocore.exceptions.ClientError as e:
error_code = int(e.response['Error']['Code'])
if error_code == 404:
exists = False
else:
current_app.logger.error(
"Unable to create s3 bucket {}".format(bucket_name))
raise e
if not exists:
s3.create_bucket(Bucket=bucket_name,
CreateBucketConfiguration={'LocationConstraint': region})
upload_id = str(uuid.uuid4())
upload_file_name = FILE_LOCATION_STRUCTURE.format(service_id, upload_id)
key = s3.Object(bucket_name, upload_file_name)
key.put(Body=contents, ServerSideEncryption='AES256')
utils_s3upload(filedata=filedata['data'],
region=region,
bucket_name=current_app.config['CSV_UPLOAD_BUCKET_NAME'],
file_location=upload_file_name)
return upload_id

View File

@@ -1,29 +1,22 @@
{% macro checkbox(
field,
hint=False,
help_link=None,
help_link_text=None,
width='2-3',
suffix=None,
block=False
width='2-3'
) %}
<label class="{% if block %}block-label{% endif %}" for="{{ field.name }}">
{{ field()}}
{{ field.label.text }}
{% if hint %}
<span class="form-hint">
{{ hint }}
</span>
{% endif %}
{% if field.errors %}
<span class="error-message">
{{ field.errors[0] }}
</span>
{% endif %}
{% if help_link and help_link_text %}
<p class="textbox-help-link">
<a href='{{ help_link }}'>{{ help_link_text }}</a>
</p>
{% endif %}
<div class="multiple-choice">
<input
id="{{ field.id }}" name="{{ field.name }}" type="checkbox" value="{{ field.data }}"
{% if field.checked %}
checked
{% endif %}
>
<label for="{{ field.id }}">
{{ field.label.text }}
{% if hint %}
<div class="hint">
{{ hint }}
</div>
{% endif %}
</label>
</div>
{% endmacro %}

View File

@@ -1,5 +1,5 @@
{% macro file_upload(field, button_text="Choose file", alternate_link=None, alternate_link_text=None) %}
<form method="post" enctype="multipart/form-data" class="{% if field.errors %}error{% endif %}" data-module="file-upload">
<form method="post" enctype="multipart/form-data" class="{% if field.errors %}form-group-error{% endif %}" data-module="file-upload">
<label class="file-upload-label" for="{{ field.name }}">
<span class="visually-hidden">{{ field.label.text }}</span>
{% if hint %}

View File

@@ -8,7 +8,7 @@
{% if error %}
<div class="validation-wrapper">
{% endif %}
<fieldset class="form-group{% if field.errors %} error{% endif %}" id="{{ field.name }}">
<fieldset class="form-group{% if field.errors %} form-group-error{% endif %}" id="{{ field.name }}">
<legend>
<span class="form-label">
{{ field.label.text }}

View File

@@ -4,7 +4,7 @@
disable=[],
option_hints={}
) %}
<div class="form-group {% if field.errors %} error{% endif %}">
<div class="form-group {% if field.errors %} form-group-error{% endif %}">
<fieldset>
<legend class="form-label">
{{ field.label.text|safe }}
@@ -15,7 +15,7 @@
{% endif %}
</legend>
{% for option in field %}
<label class="block-label" for="{{ option.id }}">
<div class="multiple-choice">
<input
id="{{ option.id }}" name="{{ option.name }}" type="radio" value="{{ option.data }}"
{% if option.data in disable %}
@@ -25,13 +25,15 @@
checked
{% endif %}
>
{{ option.label.text }}
{% if option_hints[option.data] %}
<div class="block-label-hint">
{{ option_hints[option.data] }}
</div>
{% endif %}
</label>
<label class="block-label" for="{{ option.id }}">
{{ option.label.text }}
{% if option_hints[option.data] %}
<div class="block-label-hint">
{{ option_hints[option.data] }}
</div>
{% endif %}
</label>
</div>
{% endfor %}
</fieldset>
</div>
@@ -43,7 +45,7 @@
hint=None,
wrapping_class='form-group'
) %}
<div class="{{ wrapping_class }} {% if field.errors %} error{% endif %}">
<div class="{{ wrapping_class }} {% if field.errors %} form-group-error{% endif %}">
<fieldset>
<legend class="form-label">
{{ field.label.text }}
@@ -56,10 +58,12 @@
<div class="radio-select" data-module="radio-select" data-categories="{{ field.categories|join(',') }}">
<div class="radio-select-column">
{% for option in field %}
<label class="block-label" for="{{ option.id }}">
<div class="multiple-choice">
{{ option }}
{{ option.label.text }}
</label>
<label for="{{ option.id }}">
{{ option.label.text }}
</label>
</div>
{% if loop.first %}
</div>
<div class="radio-select-column">
@@ -77,7 +81,7 @@
hint=None,
branding_dict={}
) %}
<div class="form-group {% if field.errors %} error{% endif %}">
<div class="form-group {% if field.errors %} form-group-error{% endif %}">
<fieldset>
<legend class="form-label">
{{ field.label.text }}
@@ -88,7 +92,7 @@
{% endif %}
</legend>
{% for value, option, checked in field.iter_choices() %}
<label class="block-label" for="{{ field.name }}-{{ loop.index }}">
<div class="multiple-choice">
<input
type="radio"
name="{{ field.name }}"
@@ -96,17 +100,19 @@
value="{{ value }}"
{% if checked %}checked="checked"{% endif %}
/>
{% if branding_dict.get(value, {}).get('colour') %}
<span style="background: {{ branding_dict[value].colour }}; display: inline-block; width: 3px; height: 27px"></span>
{% endif %}
{% if branding_dict.get(value, {}).get('logo') %}
<img
src="{{ branding_dict[value].logo }}"
height="27"
/>
{% endif %}
{{option}}
</label>
<label class="block-label" for="{{ field.name }}-{{ loop.index }}">
{% if branding_dict.get(value, {}).get('colour') %}
<span style="background: {{ branding_dict[value].colour }}; display: inline-block; width: 3px; height: 27px"></span>
{% endif %}
{% if branding_dict.get(value, {}).get('logo') %}
<img
src="{{ branding_dict[value].logo }}"
height="27"
/>
{% endif %}
{{option}}
</label>
</div>
{% endfor %}
</fieldset>
</div>

View File

@@ -1,7 +1,7 @@
{% from "components/big-number.html" import big_number %}
{% macro mapping_table(caption='', field_headings=[], field_headings_visible=True, caption_visible=True) -%}
<table class="table">
<table class="table table-font-xsmall">
<caption class="heading-medium table-heading{{ ' visuallyhidden' if not caption_visible}}">
{{ caption }}
</caption>

View File

@@ -11,7 +11,7 @@
safe_error_message=False,
rows=8
) %}
<div class="form-group{% if field.errors %} error{% endif %}" {% if autofocus %}data-module="autofocus"{% endif %}>
<div class="form-group{% if field.errors %} form-group-error{% endif %}" {% if autofocus %}data-module="autofocus"{% endif %}>
<label class="form-label" for="{{ field.name }}">
{% if label %}
{{ label }}
@@ -29,10 +29,20 @@
</span>
{% endif %}
</label>
{%
if highlight_tags
%}
{% set field_class = 'form-control-{} textbox-highlight-textbox'.format(width) %}
{% else %}
{% set field_class = 'form-control-{} {}'.format(width, 'textbox-right-aligned' if suffix else '') %}
{% endif %}
{%
set field_class = 'form-control ' + field_class + (
' form-control-error' if field.errors else ''
)
%}
{{ field(**{
'class':
'form-control form-control-{} textbox-highlight-textbox'.format(width) if highlight_tags else
'form-control form-control-{} {}'.format(width, 'textbox-right-aligned' if suffix else ''),
'class': field_class,
'data-module': 'highlight-tags' if highlight_tags else '',
'rows': rows|string
}) }}

View File

@@ -15,11 +15,9 @@
<form method="post">
<div class="grid-row">
<div class="column-three-quarters">
<div class="column-five-sixths">
{{ textbox(form.name, width='1-1', hint='Your recipients wont see this', rows=10) }}
{{ textbox(form.subject, width='1-1', highlight_tags=True, rows=2) }}
</div>
<div class="column-three-quarters">
{{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=8) }}
{% if current_user.has_permissions([], admin_override=True) %}
{{ radios(form.process_type) }}

View File

@@ -14,11 +14,9 @@
<form method="post">
<div class="grid-row">
<div class="column-three-quarters">
<div class="column-five-sixths">
{{ textbox(form.name, width='1-1', hint='Your recipients wont see this', rows=10) }}
{{ textbox(form.subject, width='1-1', highlight_tags=True, rows=2) }}
</div>
<div class="column-three-quarters">
{{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=8) }}
{{ page_footer(
'Save',

View File

@@ -4,9 +4,9 @@
<legend class="form-label">
Permissions
</legend>
{{ checkbox(form.send_messages, block=True) }}
{{ checkbox(form.manage_service, block=True) }}
{{ checkbox(form.manage_api_keys, block=True) }}
{{ checkbox(form.send_messages) }}
{{ checkbox(form.manage_service) }}
{{ checkbox(form.manage_api_keys) }}
</fieldset>
<div class="form-group">
@@ -18,4 +18,4 @@
<li>history of sent messages</li>
<li>who the other team members are</li>
</ul>
</div>
</div>

View File

@@ -54,7 +54,6 @@ gulp.task('copy:govuk_template:images', () => gulp.src(paths.template + 'assets/
gulp.task('javascripts', () => gulp
.src([
paths.toolkit + 'javascripts/govuk/modules.js',
paths.toolkit + 'javascripts/govuk/selection-buttons.js',
paths.src + 'javascripts/detailsPolyfill.js',
paths.src + 'javascripts/apiKey.js',
paths.src + 'javascripts/autofocus.js',

View File

@@ -21,9 +21,9 @@
"babel-core": "6.3.26",
"babel-preset-es2015": "6.3.13",
"diff-dom": "2.1.0",
"govuk-elements-sass": "1.1.1",
"govuk_frontend_toolkit": "4.6.0",
"govuk_template_jinja": "https://github.com/alphagov/govuk_template/releases/download/v0.19.1/jinja_govuk_template-0.19.1.tgz",
"govuk-elements-sass": "3.0.x",
"govuk_frontend_toolkit": "5.2.x",
"govuk_template_jinja": "0.19.x",
"gulp": "3.9.0",
"gulp-add-src": "0.2.0",
"gulp-babel": "6.1.1",

View File

@@ -28,4 +28,5 @@ notifications-python-client>=3.1,<3.2
awscli>=1.11,<1.12
awscli-cwlogs>=1.4,<1.5
git+https://github.com/alphagov/notifications-utils.git@15.0.2#egg=notifications-utils==15.0.2
git+https://github.com/alphagov/notifications-utils.git@15.0.4#egg=notifications-utils==15.0.4