diff --git a/app/assets/images/email-template/crests/data_gov_uk_x2.png b/app/assets/images/email-template/crests/data_gov_uk_x2.png
new file mode 100644
index 000000000..e006ef534
Binary files /dev/null and b/app/assets/images/email-template/crests/data_gov_uk_x2.png differ
diff --git a/app/assets/stylesheets/_grids.scss b/app/assets/stylesheets/_grids.scss
index c7becdee2..4fbd20f8f 100644
--- a/app/assets/stylesheets/_grids.scss
+++ b/app/assets/stylesheets/_grids.scss
@@ -26,6 +26,19 @@
@include grid-column(7/8);
}
+%top-gutter,
+.top-gutter {
+ @extend %contain-floats;
+ display: block;
+ margin-top: $gutter;
+ clear: both;
+}
+
+.top-gutter-4-3 {
+ @extend %top-gutter;
+ margin-top: $gutter * 4 / 3;
+}
+
%bottom-gutter,
.bottom-gutter {
@extend %contain-floats;
diff --git a/app/assets/stylesheets/components/big-number.scss b/app/assets/stylesheets/components/big-number.scss
index 2375757dd..d2cfba1b0 100644
--- a/app/assets/stylesheets/components/big-number.scss
+++ b/app/assets/stylesheets/components/big-number.scss
@@ -129,3 +129,26 @@
}
}
+
+.big-number-meta-wrapper {
+
+ position: relative;
+ margin: $gutter-half 0 $gutter 0;
+ background: $govuk-blue;
+
+ .big-number-meta {
+
+ padding: ($gutter / 3) $gutter-half;
+ color: $white;
+ pointer-events: none;
+
+ @include media(desktop) {
+ position: absolute;
+ bottom: 7px;
+ right: 5px;
+ text-align: right;
+ }
+
+ }
+
+}
diff --git a/app/assets/stylesheets/components/page-footer.scss b/app/assets/stylesheets/components/page-footer.scss
index 04b6a31b1..e40c42a35 100644
--- a/app/assets/stylesheets/components/page-footer.scss
+++ b/app/assets/stylesheets/components/page-footer.scss
@@ -59,3 +59,21 @@
}
}
+
+.align-button-with-textbox {
+
+ .button {
+
+ @include media(desktop) {
+ position: relative;
+ top: 32px;
+ left: -30px;
+ width: 100%;
+ margin-right: -30px;
+ padding-top: 8px;
+ box-sizing: content-box;
+ }
+
+ }
+
+}
diff --git a/app/assets/stylesheets/components/sms-message.scss b/app/assets/stylesheets/components/sms-message.scss
index a5a79e6d6..96efbf308 100644
--- a/app/assets/stylesheets/components/sms-message.scss
+++ b/app/assets/stylesheets/components/sms-message.scss
@@ -1,6 +1,8 @@
-%sms-message-wrapper,
+$tail-angle: 20deg;
+
.sms-message-wrapper {
+ position: relative;
width: 100%;
max-width: 464px;
box-sizing: border-box;
@@ -13,21 +15,20 @@
clear: both;
word-wrap: break-word;
- p {
- margin: 0;
- line-height: 1.6;
+ &:after {
+ content: "";
+ display: block;
+ position: absolute;
+ bottom: -4px;
+ right: -20px;
+ border: 10px solid transparent;
+ border-left-width: 13px;
+ border-right-width: 13px;
+ border-bottom-color: $panel-colour;
+ border-left-color: $panel-colour;
+ transform: rotate($tail-angle);
}
- p + p {
- margin-top: 20px;
- }
-
-}
-
-.sms-message-wrapper-with-radio {
- @extend %sms-message-wrapper;
- padding-left: 45px;
- cursor: pointer;
}
.sms-message-recipient {
@@ -35,22 +36,3 @@
color: $secondary-text-colour;
margin: 10px 0 0 0;
}
-
-.sms-message-name {
- @include bold-24;
- margin: 20px 0 5px 0;
-}
-
-.sms-message-picker {
- display: block;
- margin: 7px 0 0 0;
- position: absolute;
- left: 15px;
- top: 50%;
- z-index: 50;
-}
-
-.sms-message-from {
- @include bold-19;
- display: block;
-}
diff --git a/app/assets/stylesheets/components/table.scss b/app/assets/stylesheets/components/table.scss
index 085b16e6f..152d209be 100644
--- a/app/assets/stylesheets/components/table.scss
+++ b/app/assets/stylesheets/components/table.scss
@@ -74,6 +74,12 @@
}
+ &-invisible-error {
+ border-left: 5px solid transparent;
+ padding-left: 7px;
+ display: block;
+ }
+
&-status {
&-default {
@@ -123,6 +129,7 @@
}
&-index {
+ @include bold-16;
width: 15px;
}
@@ -132,6 +139,10 @@
}
+.table-font-xsmall td.table-field-index { // overrides GOV.UK Elements
+ @include bold-16;
+}
+
.table-field-headings,
.table-field-headings-visible {
@@ -199,3 +210,11 @@ a.table-show-more-link {
border-bottom: 1px solid $border-colour;
padding: 0.75em 0 0.5625em 0;
}
+
+.wide-left-hand-column {
+ display: block;
+ max-width: 560px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
diff --git a/app/assets/stylesheets/views/dashboard.scss b/app/assets/stylesheets/views/dashboard.scss
index a99623384..a1fed973a 100644
--- a/app/assets/stylesheets/views/dashboard.scss
+++ b/app/assets/stylesheets/views/dashboard.scss
@@ -94,3 +94,7 @@
}
}
+
+.align-with-message-body {
+ margin-top: $gutter * 5 / 6;
+}
diff --git a/app/config.py b/app/config.py
index 32cbe76d4..c19849a7e 100644
--- a/app/config.py
+++ b/app/config.py
@@ -57,9 +57,7 @@ class Config(object):
CSV_UPLOAD_BUCKET_NAME = 'local-notifications-csv-upload'
DESKPRO_PERSON_EMAIL = 'donotreply@notifications.service.gov.uk'
ACTIVITY_STATS_LIMIT_DAYS = 7
- TEST_MESSAGE_FILENAME = 'Test message'
-
- SMS_FREE_TIER_AMOUNT = 250000
+ TEST_MESSAGE_FILENAME = 'Report'
STATSD_ENABLED = False
STATSD_HOST = "statsd.hostedgraphite.com"
@@ -83,6 +81,8 @@ class Config(object):
r"hmcts\.net",
r"scotent\.co\.uk",
r"assembly\.wales",
+ r"cjsm\.net",
+ r"cqc\.org\.uk",
]
@@ -100,6 +100,7 @@ class Test(Development):
WTF_CSRF_ENABLED = False
CSV_UPLOAD_BUCKET_NAME = 'test-notifications-csv-upload'
NOTIFY_ENVIRONMENT = 'test'
+ TEMPLATE_PREVIEW_API_HOST = 'http://localhost:9999'
class Preview(Config):
diff --git a/app/main/forms.py b/app/main/forms.py
index 34a6d8616..f8db6e577 100644
--- a/app/main/forms.py
+++ b/app/main/forms.py
@@ -7,6 +7,7 @@ from notifications_utils.recipients import (
validate_phone_number,
InvalidPhoneError
)
+from notifications_utils.columns import Columns
from wtforms import (
validators,
StringField,
@@ -102,11 +103,26 @@ class UKMobileNumber(TelField):
raise ValidationError(str(e))
-def mobile_number():
- return UKMobileNumber('Mobile number',
+class InternationalPhoneNumber(TelField):
+ def pre_validate(self, form):
+ try:
+ validate_phone_number(self.data, international=True)
+ except InvalidPhoneError as e:
+ raise ValidationError(str(e))
+
+
+def mobile_number(label='Mobile number'):
+ return UKMobileNumber(label,
validators=[DataRequired(message='Can’t be empty')])
+def international_phone_number(label='Mobile number'):
+ return InternationalPhoneNumber(
+ label,
+ validators=[DataRequired(message='Can’t be empty')]
+ )
+
+
def password(label='Password'):
return PasswordField(label,
validators=[DataRequired(message='Can’t be empty'),
@@ -502,7 +518,11 @@ class ServiceSmsSender(Form):
class ServiceLetterContactBlock(Form):
- letter_contact_block = TextAreaField()
+ letter_contact_block = TextAreaField(
+ validators=[
+ NoCommasInPlaceHolders()
+ ]
+ )
def validate_letter_contact_block(form, field):
line_count = field.data.strip().count('\n')
@@ -621,6 +641,11 @@ class SearchTemplatesForm(Form):
search = SearchField('Search by name')
+class SearchNotificationsForm(Form):
+
+ to = SearchField('Search by phone number or email address')
+
+
class PlaceholderForm(Form):
pass
@@ -629,15 +654,25 @@ class PlaceholderForm(Form):
def get_placeholder_form_instance(
placeholder_name,
dict_to_populate_from,
- optional_placeholder=False
+ optional_placeholder=False,
+ allow_international_phone_numbers=False,
):
- PlaceholderForm.placeholder_value = StringField(
- placeholder_name,
- validators=[
+ if Columns.make_key(placeholder_name) == 'emailaddress':
+ field = email_address(label=placeholder_name, gov_user=False)
+ elif Columns.make_key(placeholder_name) == 'phonenumber':
+ if allow_international_phone_numbers:
+ field = international_phone_number(label=placeholder_name)
+ else:
+ field = mobile_number(label=placeholder_name)
+ elif optional_placeholder:
+ field = StringField(placeholder_name)
+ else:
+ field = StringField(placeholder_name, validators=[
DataRequired(message='Can’t be empty')
- ] if not optional_placeholder else []
- )
+ ])
+
+ PlaceholderForm.placeholder_value = field
return PlaceholderForm(
placeholder_value=dict_to_populate_from.get(placeholder_name, '')
diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py
index 45736ac1e..4e8893f67 100644
--- a/app/main/views/dashboard.py
+++ b/app/main/views/dashboard.py
@@ -2,7 +2,6 @@ from datetime import datetime
from functools import partial
from flask import (
render_template,
- current_app,
url_for,
session,
jsonify,
@@ -13,6 +12,7 @@ from flask_login import login_required
from app.main import main
from app import (
+ current_service,
job_api_client,
service_api_client,
template_statistics_client
@@ -136,6 +136,20 @@ def monthly(service_id):
)
+@main.route("/services/
- {{ text }}
+ {{ text if text != None else caller() }}
{%- endmacro %}
diff --git a/app/templates/views/activity/notifications.html b/app/templates/views/activity/notifications.html
index 42c6cf169..06158fb75 100644
--- a/app/templates/views/activity/notifications.html
+++ b/app/templates/views/activity/notifications.html
@@ -21,7 +21,10 @@
{{ item.to }}
- {% if item.job %} + {% if item.job and item.job.original_file_name == 'Report' %} + {{ item.template.name }} + sent to one recipient + {% elif item.job %} From {{ item.job.original_file_name }} {% else %} {{ item.template.name }} diff --git a/app/templates/views/check.html b/app/templates/views/check.html index 933bda753..d7819fca2 100644 --- a/app/templates/views/check.html +++ b/app/templates/views/check.html @@ -150,7 +150,9 @@ {% endif %} - {{ template|string }} + {% if not errors %} + {{ template|string }} + {% endif %}
+ Showing all {{ messages | length }} messages +
+ {% endif %} +