mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-02 17:48:50 -04:00
Merge pull request #449 from alphagov/detect-placeholders-in-email-subject
Detect placeholders in email subject
This commit is contained in:
@@ -7,25 +7,6 @@
|
|||||||
|
|
||||||
const tagPattern = /\(\([^\)\(]+\)\)/g;
|
const tagPattern = /\(\([^\)\(]+\)\)/g;
|
||||||
|
|
||||||
const getPlaceholderHint = function(placeholders) {
|
|
||||||
if (0 === placeholders.length) {
|
|
||||||
return `
|
|
||||||
<p>Add fields using ((double brackets))</p>
|
|
||||||
<span class='placeholder-hint-action' tabindex='0' role='button'>Show me how</span>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
if (1 === placeholders.length) {
|
|
||||||
return `
|
|
||||||
<p>Add fields using ((double brackets))</p>
|
|
||||||
<p>You’ll populate the ‘${placeholders[0]}’ field when you send messages using this template</p>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
return `
|
|
||||||
<p>Add fields using ((double brackets))</p>
|
|
||||||
<p>You’ll populate your fields when you send some messages</p>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
Modules.HighlightTags = function() {
|
Modules.HighlightTags = function() {
|
||||||
|
|
||||||
this.start = function(textarea) {
|
this.start = function(textarea) {
|
||||||
@@ -41,9 +22,6 @@
|
|||||||
`))
|
`))
|
||||||
.on("input", this.update);
|
.on("input", this.update);
|
||||||
|
|
||||||
this.$placeHolderHint = $('#placeholder-hint')
|
|
||||||
.on("click", ".placeholder-hint-action", this.demo);
|
|
||||||
|
|
||||||
this.initialHeight = this.$textbox.height();
|
this.initialHeight = this.$textbox.height();
|
||||||
|
|
||||||
this.$backgroundMaskForeground.css({
|
this.$backgroundMaskForeground.css({
|
||||||
@@ -65,29 +43,13 @@
|
|||||||
|
|
||||||
this.escapedMessage = () => $('<div/>').text(this.$textbox.val()).html();
|
this.escapedMessage = () => $('<div/>').text(this.$textbox.val()).html();
|
||||||
|
|
||||||
this.listPlaceholders = () => this.escapedMessage().match(tagPattern) || [];
|
|
||||||
|
|
||||||
this.listPlaceholdersWithoutBrackets = () => this.listPlaceholders().map(
|
|
||||||
placeholder => placeholder.substring(2, placeholder.length - 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.replacePlaceholders = () => this.$backgroundMaskForeground.html(
|
this.replacePlaceholders = () => this.$backgroundMaskForeground.html(
|
||||||
this.escapedMessage().replace(
|
this.escapedMessage().replace(
|
||||||
tagPattern, match => `<span class='tag'>${match}</span>`
|
tagPattern, match => `<span class='tag'>${match}</span>`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.hint = () => this.$placeHolderHint.html(
|
this.update = () => this.replacePlaceholders() && this.resize();
|
||||||
getPlaceholderHint(this.listPlaceholdersWithoutBrackets())
|
|
||||||
);
|
|
||||||
|
|
||||||
this.update = () => (
|
|
||||||
this.replacePlaceholders() && this.resize() && this.hint()
|
|
||||||
);
|
|
||||||
|
|
||||||
this.demo = () => (
|
|
||||||
this.$textbox.val((i, current) => `Dear ((name)), ${current}`) && this.update()
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
75
app/assets/javascripts/placeholderHint.js
Normal file
75
app/assets/javascripts/placeholderHint.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
(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}
|
||||||
|
<span class='placeholder-hint-action' tabindex='0' role='button'>Show me how</span>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
if (1 === placeholders.length) {
|
||||||
|
return `
|
||||||
|
${this.originalHTML}
|
||||||
|
<p>You’ll populate the ‘${placeholders[0]}’ field when you send messages using this template</p>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
return `
|
||||||
|
${this.originalHTML}
|
||||||
|
<p>You’ll populate your fields when you send some messages</p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
this.escapedMessages = () => $('<div/>').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);
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
resize: none;
|
resize: none;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
background: none;
|
background: none;
|
||||||
height: 200px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-textbox,
|
&-textbox,
|
||||||
@@ -36,7 +35,7 @@
|
|||||||
color: transparent;
|
color: transparent;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
padding-bottom: $gutter;
|
padding-bottom: $gutter-half;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-background {
|
&-background {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class SMSTemplateForm(Form):
|
|||||||
|
|
||||||
class EmailTemplateForm(SMSTemplateForm):
|
class EmailTemplateForm(SMSTemplateForm):
|
||||||
|
|
||||||
subject = StringField(
|
subject = TextAreaField(
|
||||||
u'Subject',
|
u'Subject',
|
||||||
validators=[DataRequired(message="Can’t be empty")])
|
validators=[DataRequired(message="Can’t be empty")])
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
help_link_text=None,
|
help_link_text=None,
|
||||||
width='2-3',
|
width='2-3',
|
||||||
suffix=None,
|
suffix=None,
|
||||||
disabled=False,
|
safe_error_message=False,
|
||||||
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 %} error{% endif %}" {% if autofocus %}data-module="autofocus"{% endif %}>
|
||||||
<label class="form-label" for="{{ field.name }}">
|
<label class="form-label" for="{{ field.name }}">
|
||||||
@@ -24,21 +24,11 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</label>
|
</label>
|
||||||
{% if disabled %}
|
{{ field(**{
|
||||||
<p>{{ 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': '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 ''),
|
'data-module': 'highlight-tags' if highlight_tags else '',
|
||||||
'data-module': 'highlight-tags' if highlight_tags else '',
|
'rows': rows|string
|
||||||
'disabled': 'disabled'
|
}) }}
|
||||||
}) }}
|
|
||||||
</p>
|
|
||||||
{% 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 ''),
|
|
||||||
'data-module': 'highlight-tags' if highlight_tags else ''
|
|
||||||
}) }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
{% if suffix %}
|
{% if suffix %}
|
||||||
<span>{{ suffix }}</span>
|
<span>{{ suffix }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
<form method="post">
|
<form method="post">
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="column-two-thirds">
|
<div class="column-two-thirds">
|
||||||
{{ textbox(form.name, width='1-1', hint='Your recipients won’t see this') }}
|
{{ textbox(form.name, width='1-1', hint='Your recipients won’t see this', rows=10) }}
|
||||||
{{ textbox(form.subject, width='1-1') }}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="column-two-thirds">
|
<div class="column-two-thirds">
|
||||||
{{ textbox(form.template_content, highlight_tags=True, width='1-1') }}
|
{{ 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(
|
{{ page_footer(
|
||||||
'Save',
|
'Save',
|
||||||
delete_link=url_for('.delete_service_template', service_id=current_service.id, template_id=template_id) if template_id or None,
|
delete_link=url_for('.delete_service_template', service_id=current_service.id, template_id=template_id) if template_id or None,
|
||||||
@@ -27,9 +27,9 @@
|
|||||||
) }}
|
) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="column-one-third">
|
<div class="column-one-third">
|
||||||
<label for='template_content' class='placeholder-hint'>
|
<label for='template_content' class='placeholder-hint banner-mode' data-module='placeholder-hint' data-textboxes-selector='#template_content,#subject' data-target-textbox-selector="#template_content">
|
||||||
<div class="banner-mode" id="placeholder-hint" aria-live="polite">
|
<div class="" id="placeholder-hint" aria-live="polite">
|
||||||
<p>Add fields using ((double brackets))</p>
|
<p>Add fields to the subject or message content using ((double brackets))</p>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ gulp.task('javascripts', () => gulp
|
|||||||
paths.src + 'javascripts/fileUpload.js',
|
paths.src + 'javascripts/fileUpload.js',
|
||||||
paths.src + 'javascripts/updateContent.js',
|
paths.src + 'javascripts/updateContent.js',
|
||||||
paths.src + 'javascripts/expandCollapse.js',
|
paths.src + 'javascripts/expandCollapse.js',
|
||||||
|
paths.src + 'javascripts/placeholderHint.js',
|
||||||
paths.src + 'javascripts/main.js'
|
paths.src + 'javascripts/main.js'
|
||||||
])
|
])
|
||||||
.pipe(plugins.babel({
|
.pipe(plugins.babel({
|
||||||
|
|||||||
Reference in New Issue
Block a user