From eed554ebb87a8b66d9941dcf9e4c6733a1ebb4a6 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Mon, 20 Jun 2016 11:37:42 +0100 Subject: [PATCH 1/7] Give the textbox on edit template a better label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ‘Message content’ is very much _our_ name for the thing. ‘Message’ is more human-friendly. --- app/main/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main/forms.py b/app/main/forms.py index 38c72b1c2..befcb1ca4 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -198,7 +198,7 @@ class SMSTemplateForm(Form): validators=[DataRequired(message="Can’t be empty")]) template_content = TextAreaField( - u'Message content', + u'Message', validators=[ DataRequired(message="Can’t be empty"), NoCommasInPlaceHolders() From 3fa0e3aa6624e06f400839eeaa1cd0c407e49e2d Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Mon, 20 Jun 2016 11:38:30 +0100 Subject: [PATCH 2/7] Give more guidance about what to put in templates There are some common questions that keep coming up when users are editing or creating templates. This commit adds a pattern for sections of guidance which can be shown/hidden. It then modifies the guidance as follows. Change: - guidance about placeholders; give an example about what to do and what not to do (because the mistake we keep seeing people make is putting the thing itself, not the name of the thing) Add (pretty basic at the moment but a need for these has come out of research): - guidance about links - guidance about message length for text messages --- .../stylesheets/components/secondary-button.scss | 9 +++++++++ .../templates/guidance-character-count.html | 12 ++++++++++++ .../partials/templates/guidance-links.html | 8 ++++++++ .../templates/guidance-personalisation.html | 14 ++++++++++++++ app/templates/views/edit-email-template.html | 14 ++++++-------- app/templates/views/edit-sms-template.html | 15 +++++++-------- 6 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 app/templates/partials/templates/guidance-character-count.html create mode 100644 app/templates/partials/templates/guidance-links.html create mode 100644 app/templates/partials/templates/guidance-personalisation.html diff --git a/app/assets/stylesheets/components/secondary-button.scss b/app/assets/stylesheets/components/secondary-button.scss index 6e7a0ff7c..2aef3ffb4 100644 --- a/app/assets/stylesheets/components/secondary-button.scss +++ b/app/assets/stylesheets/components/secondary-button.scss @@ -6,3 +6,12 @@ padding-right: 0; text-align: center; } + +.tertiary-button { + @include button($grey-3); + padding: 0.3em 0.1em 0.2em 0.1em; + width: 100%; + padding-left: 0; + padding-right: 0; + text-align: left; +} diff --git a/app/templates/partials/templates/guidance-character-count.html b/app/templates/partials/templates/guidance-character-count.html new file mode 100644 index 000000000..b11dae62e --- /dev/null +++ b/app/templates/partials/templates/guidance-character-count.html @@ -0,0 +1,12 @@ +
+ Message length +
+

+ If your message is long then it will + cost more. +

+

+ See pricing for details. +

+
+
diff --git a/app/templates/partials/templates/guidance-links.html b/app/templates/partials/templates/guidance-links.html new file mode 100644 index 000000000..2d0b7131e --- /dev/null +++ b/app/templates/partials/templates/guidance-links.html @@ -0,0 +1,8 @@ +
+ Links and URLs +
+

+ Always use full URLs, including the http:// +

+
+
diff --git a/app/templates/partials/templates/guidance-personalisation.html b/app/templates/partials/templates/guidance-personalisation.html new file mode 100644 index 000000000..c395f42e6 --- /dev/null +++ b/app/templates/partials/templates/guidance-personalisation.html @@ -0,0 +1,14 @@ +
+ Personalisation +
+

+ Use double brackets to add personalisation. +

+

+ Yes: ((name)) +

+

+ No: ((Helen)) +

+
+
diff --git a/app/templates/views/edit-email-template.html b/app/templates/views/edit-email-template.html index ab0492963..1e3db961c 100644 --- a/app/templates/views/edit-email-template.html +++ b/app/templates/views/edit-email-template.html @@ -16,9 +16,9 @@
{{ textbox(form.name, width='1-1', hint='Your recipients won’t see this', rows=10) }} + {{ textbox(form.subject, width='1-1', highlight_tags=True, rows=2) }}
- {{ textbox(form.subject, width='1-1', highlight_tags=True, rows=2) }} {{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=8) }} {{ page_footer( 'Save', @@ -26,13 +26,11 @@ delete_link_text='Delete this template' ) }}
-
- -
+
diff --git a/app/templates/views/edit-sms-template.html b/app/templates/views/edit-sms-template.html index ee4778fa9..45d6d7fe4 100644 --- a/app/templates/views/edit-sms-template.html +++ b/app/templates/views/edit-sms-template.html @@ -18,20 +18,19 @@ {{ textbox(form.name, width='1-1', hint='Your recipients won’t see this') }}
- {{ textbox(form.template_content, highlight_tags=True, width='1-1') }} + {{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=5) }} {{ page_footer( 'Save', delete_link=url_for('.delete_service_template', service_id=current_service.id, template_id=template_id) if template_id or None, delete_link_text='Delete this template' ) }}
-
- -
+ From fbc4abf85d8c094adcb71bdd05c3a76b33c318b4 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Thu, 16 Jun 2016 17:04:53 +0100 Subject: [PATCH 3/7] Add character count as you type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Text messages have a maximum length, which we tell the users. We shouldn’t expect people to count the characters in the message themselves. This commit borrows [the word counter from the Digital Marketplace frontend toolkit](https://github.com/alphagov/digitalmarketplace-frontend-toolkit/blob/9d17690de5a030ac0466cfff6f774c26e9e42680/toolkit/javascripts/word-counter.js) and adapts it to count characters instead. Things I’m still not sure about with this: - what should it say when the message goes over the length of one text message - what’s the interaction with placeholders, which will change the length of the message This commit also adds a line to the pricing page which explains that service name counts towards the length of the message. --- app/assets/javascripts/characterCount.js | 39 +++++++++++++++++++ .../stylesheets/components/textbox.scss | 6 +++ app/templates/components/textbox.html | 11 +++++- app/templates/views/edit-sms-template.html | 9 ++++- app/templates/views/pricing.html | 15 ++++--- gulpfile.babel.js | 1 + tests/app/main/views/test_templates.py | 10 +++-- 7 files changed, 79 insertions(+), 12 deletions(-) create mode 100644 app/assets/javascripts/characterCount.js diff --git a/app/assets/javascripts/characterCount.js b/app/assets/javascripts/characterCount.js new file mode 100644 index 000000000..97232c615 --- /dev/null +++ b/app/assets/javascripts/characterCount.js @@ -0,0 +1,39 @@ +(function(Modules) { + "use strict"; + + Modules.CharacterCount = function() { + + this.start = function(component) { + + var getCharacterCount = () => + ($textarea.val()).length; + + var getLengthOfOneMessage = () => + 160 - (serviceName + ': ').length; + + var $component = $(component); + + var serviceName = $component.data('service-name'); + + var $textarea = $('textarea', $component) + .eq(0) + .on('change keyup paste', () => $counter.html(` + ${getCharacterCount()} of ${getLengthOfOneMessage()} characters + `)); + + $component + .append($counter = $(` +

+ `)); + + $textarea + .trigger('change'); + + }; + + }; + +})(window.GOVUK.Modules); diff --git a/app/assets/stylesheets/components/textbox.scss b/app/assets/stylesheets/components/textbox.scss index 27ee0d1f8..d49b0c6c6 100644 --- a/app/assets/stylesheets/components/textbox.scss +++ b/app/assets/stylesheets/components/textbox.scss @@ -54,3 +54,9 @@ .textbox-right-aligned { text-align: right; } + +.textbox-character-count { + @include core-19($tabular-numbers: true); + margin: 10px 0 0 0; + color: $secondary-text-colour; +} diff --git a/app/templates/components/textbox.html b/app/templates/components/textbox.html index 40d141072..cfd6f15d2 100644 --- a/app/templates/components/textbox.html +++ b/app/templates/components/textbox.html @@ -9,9 +9,16 @@ width='2-3', suffix=None, safe_error_message=False, - rows=8 + rows=8, + character_count=False, + service_name=None ) %} -

+
- {{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=5) }} + {{ textbox( + form.template_content, + highlight_tags=True, + character_count=True, + width='1-1', + service_name=current_service.name, + rows=5 + ) }} {{ page_footer( 'Save', delete_link=url_for('.delete_service_template', service_id=current_service.id, template_id=template_id) if template_id or None, diff --git a/app/templates/views/pricing.html b/app/templates/views/pricing.html index 34f47e3f5..d92cd0d68 100644 --- a/app/templates/views/pricing.html +++ b/app/templates/views/pricing.html @@ -20,12 +20,15 @@
  • Free allowance: 250,000 text messages per service, per financial year
  • -
  • If your messages are long, they will count as 2 or 3 text messages, depending on length: -
      -
    • Up to 160 characters = 1 text message
    • -
    • Up to 306 characters = 2 text messages
    • -
    • Up to 459 characters = 3 text messages
    • -
  • +
  • + If your messages are long, they will count as 2 or 3 text messages, depending on length: +
      +
    • Up to 160 characters = 1 text message
    • +
    • Up to 306 characters = 2 text messages
    • +
    • Up to 459 characters = 3 text messages
    • +
    • Your service name counts towards the length of your message
    • +
    +
  • Standard text message rate: 1.8p + VAT
diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 1f8ee9e50..013fd3f2f 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -61,6 +61,7 @@ gulp.task('javascripts', () => gulp paths.src + 'javascripts/updateContent.js', paths.src + 'javascripts/expandCollapse.js', paths.src + 'javascripts/placeholderHint.js', + paths.src + 'javascripts/characterCount.js', paths.src + 'javascripts/main.js' ]) .pipe(plugins.babel({ diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py index 952ed1d49..c9ae21957 100644 --- a/tests/app/main/views/test_templates.py +++ b/tests/app/main/views/test_templates.py @@ -29,10 +29,14 @@ def test_should_show_page_for_one_templates(app_, template_id=template_id)) assert response.status_code == 200 - assert "Two week reminder" in response.get_data(as_text=True) - assert "Your vehicle tax is about to expire" in response.get_data(as_text=True) + content = response.get_data(as_text=True) + assert "Two week reminder" in content + assert "Your vehicle tax is about to expire" in content + assert 'data-module="character-count"' in content + assert 'data-service-name="Test Service"' in content mock_get_service_template.assert_called_with( - service_id, template_id) + service_id, template_id + ) def test_should_redirect_when_saving_a_template(app_, From c975e0f6716477d0e8bcf648472dcb5d7d070e4c Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Mon, 20 Jun 2016 11:39:13 +0100 Subject: [PATCH 4/7] Remove placeholder hint JS This was used for an older iteration of placeholder guidance. Not used anywhere now. --- app/assets/javascripts/placeholderHint.js | 75 ----------------------- gulpfile.babel.js | 1 - 2 files changed, 76 deletions(-) delete mode 100644 app/assets/javascripts/placeholderHint.js diff --git a/app/assets/javascripts/placeholderHint.js b/app/assets/javascripts/placeholderHint.js deleted file mode 100644 index bf73cd805..000000000 --- a/app/assets/javascripts/placeholderHint.js +++ /dev/null @@ -1,75 +0,0 @@ -(function(Modules) { - "use strict"; - - if ( - !('oninput' in document.createElement('input')) - ) return; - - const tagPattern = /\(\([^\)\(]+\)\)/g; - - Modules.PlaceholderHint = function() { - - this.start = function(component) { - - this.$component = $(component); - this.originalHTML = this.$component.html(); - this.$allTextboxes = $(this.$component.data('textboxes-selector')); - this.$targetTextbox = $(this.$component.data('target-textbox-selector')); - - this.$component - .on('click', '.placeholder-hint-action', this.demo); - - this.$allTextboxes - .on('input', this.hint) - .trigger('input'); - - }; - - this.getPlaceholderHint = function() { - - let placeholders = this.listPlaceholdersWithoutBrackets(); - - if (0 === placeholders.length) { - return ` - ${this.originalHTML} - Show me how - `; - } - if (1 === placeholders.length) { - return ` - ${this.originalHTML} -

You’ll populate the ‘${placeholders[0]}’ field when you send messages using this template

- `; - } - return ` - ${this.originalHTML} -

You’ll populate your fields when you send some messages

- `; - - }; - - this.escapedMessages = () => $('
').text( - this.$allTextboxes.map(function() { - return $(this).val(); - }).get() - ).html(); - - this.listPlaceholders = () => this.escapedMessages().match(tagPattern) || []; - - this.listPlaceholdersWithoutBrackets = () => this.listPlaceholders().map( - placeholder => placeholder.substring(2, placeholder.length - 2) - ); - - this.renderDemo = () => this.$targetTextbox.val((i, current) => `Dear ((name)), ${current}`); - - this.hint = () => this.$component.html( - this.getPlaceholderHint() - ); - - this.demo = () => ( - this.renderDemo() && this.$targetTextbox.trigger('input') && this.hint() - ); - - }; - -})(window.GOVUK.Modules); diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 013fd3f2f..d66b45257 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -60,7 +60,6 @@ gulp.task('javascripts', () => gulp paths.src + 'javascripts/fileUpload.js', paths.src + 'javascripts/updateContent.js', paths.src + 'javascripts/expandCollapse.js', - paths.src + 'javascripts/placeholderHint.js', paths.src + 'javascripts/characterCount.js', paths.src + 'javascripts/main.js' ]) From cc95f52f3fd8022c05894c74b9e19442ca3fda45 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Mon, 20 Jun 2016 15:56:22 +0100 Subject: [PATCH 5/7] Use HTTPS in the URL example HTTPS protocol is best protocol. --- app/templates/partials/templates/guidance-links.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/partials/templates/guidance-links.html b/app/templates/partials/templates/guidance-links.html index 2d0b7131e..2d7aab039 100644 --- a/app/templates/partials/templates/guidance-links.html +++ b/app/templates/partials/templates/guidance-links.html @@ -2,7 +2,7 @@ Links and URLs

- Always use full URLs, including the http:// + Always use full URLs, starting with https://

From be80c501d7c0d30ecd2b64262213f1fb9ac7c80e Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Mon, 20 Jun 2016 15:59:39 +0100 Subject: [PATCH 6/7] Use less confusing terminology than yes/no MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yes/no is quite ambiguous. Correct/incorrect is more formal, but clearer. Right/wrong doesn’t feel quite right. Good/bad is definitely not right. --- .../partials/templates/guidance-personalisation.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/partials/templates/guidance-personalisation.html b/app/templates/partials/templates/guidance-personalisation.html index c395f42e6..3cae73723 100644 --- a/app/templates/partials/templates/guidance-personalisation.html +++ b/app/templates/partials/templates/guidance-personalisation.html @@ -5,10 +5,10 @@ Use double brackets to add personalisation.

- Yes: ((name)) + Correct: ((name))

- No: ((Helen)) + Incorrect: ((Helen))

From d2b4dd5007396d72a720d796238dbe9e976c9b85 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Mon, 20 Jun 2016 16:00:42 +0100 Subject: [PATCH 7/7] Revert "Add character count as you type" This reverts commit fbc4abf85d8c094adcb71bdd05c3a76b33c318b4. --- app/assets/javascripts/characterCount.js | 39 ------------------- .../stylesheets/components/textbox.scss | 6 --- app/templates/components/textbox.html | 11 +----- app/templates/views/edit-sms-template.html | 9 +---- app/templates/views/pricing.html | 15 +++---- gulpfile.babel.js | 1 - tests/app/main/views/test_templates.py | 10 ++--- 7 files changed, 12 insertions(+), 79 deletions(-) delete mode 100644 app/assets/javascripts/characterCount.js diff --git a/app/assets/javascripts/characterCount.js b/app/assets/javascripts/characterCount.js deleted file mode 100644 index 97232c615..000000000 --- a/app/assets/javascripts/characterCount.js +++ /dev/null @@ -1,39 +0,0 @@ -(function(Modules) { - "use strict"; - - Modules.CharacterCount = function() { - - this.start = function(component) { - - var getCharacterCount = () => - ($textarea.val()).length; - - var getLengthOfOneMessage = () => - 160 - (serviceName + ': ').length; - - var $component = $(component); - - var serviceName = $component.data('service-name'); - - var $textarea = $('textarea', $component) - .eq(0) - .on('change keyup paste', () => $counter.html(` - ${getCharacterCount()} of ${getLengthOfOneMessage()} characters - `)); - - $component - .append($counter = $(` -

- `)); - - $textarea - .trigger('change'); - - }; - - }; - -})(window.GOVUK.Modules); diff --git a/app/assets/stylesheets/components/textbox.scss b/app/assets/stylesheets/components/textbox.scss index d49b0c6c6..27ee0d1f8 100644 --- a/app/assets/stylesheets/components/textbox.scss +++ b/app/assets/stylesheets/components/textbox.scss @@ -54,9 +54,3 @@ .textbox-right-aligned { text-align: right; } - -.textbox-character-count { - @include core-19($tabular-numbers: true); - margin: 10px 0 0 0; - color: $secondary-text-colour; -} diff --git a/app/templates/components/textbox.html b/app/templates/components/textbox.html index cfd6f15d2..40d141072 100644 --- a/app/templates/components/textbox.html +++ b/app/templates/components/textbox.html @@ -9,16 +9,9 @@ width='2-3', suffix=None, safe_error_message=False, - rows=8, - character_count=False, - service_name=None + rows=8 ) %} -

+
- {{ textbox( - form.template_content, - highlight_tags=True, - character_count=True, - width='1-1', - service_name=current_service.name, - rows=5 - ) }} + {{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=5) }} {{ page_footer( 'Save', delete_link=url_for('.delete_service_template', service_id=current_service.id, template_id=template_id) if template_id or None, diff --git a/app/templates/views/pricing.html b/app/templates/views/pricing.html index d92cd0d68..34f47e3f5 100644 --- a/app/templates/views/pricing.html +++ b/app/templates/views/pricing.html @@ -20,15 +20,12 @@
  • Free allowance: 250,000 text messages per service, per financial year
  • -
  • - If your messages are long, they will count as 2 or 3 text messages, depending on length: -
      -
    • Up to 160 characters = 1 text message
    • -
    • Up to 306 characters = 2 text messages
    • -
    • Up to 459 characters = 3 text messages
    • -
    • Your service name counts towards the length of your message
    • -
    -
  • +
  • If your messages are long, they will count as 2 or 3 text messages, depending on length: +
      +
    • Up to 160 characters = 1 text message
    • +
    • Up to 306 characters = 2 text messages
    • +
    • Up to 459 characters = 3 text messages
    • +
  • Standard text message rate: 1.8p + VAT
diff --git a/gulpfile.babel.js b/gulpfile.babel.js index d66b45257..c97144b44 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -60,7 +60,6 @@ gulp.task('javascripts', () => gulp paths.src + 'javascripts/fileUpload.js', paths.src + 'javascripts/updateContent.js', paths.src + 'javascripts/expandCollapse.js', - paths.src + 'javascripts/characterCount.js', paths.src + 'javascripts/main.js' ]) .pipe(plugins.babel({ diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py index c9ae21957..952ed1d49 100644 --- a/tests/app/main/views/test_templates.py +++ b/tests/app/main/views/test_templates.py @@ -29,14 +29,10 @@ def test_should_show_page_for_one_templates(app_, template_id=template_id)) assert response.status_code == 200 - content = response.get_data(as_text=True) - assert "Two week reminder" in content - assert "Your vehicle tax is about to expire" in content - assert 'data-module="character-count"' in content - assert 'data-service-name="Test Service"' in content + assert "Two week reminder" in response.get_data(as_text=True) + assert "Your vehicle tax is about to expire" in response.get_data(as_text=True) mock_get_service_template.assert_called_with( - service_id, template_id - ) + service_id, template_id) def test_should_redirect_when_saving_a_template(app_,