Add find-as-you-type on the choose template page

Not everyone knows how to use `ctrl` + `f`, and it’s not scoped to
just the list of templates.

The template you want to work with is often not the first one in the
list, but ordering by created at is useful for other reasons (mainly
around first time use).

This commit adds a find as you type control which aims to give users a
quick way of getting to the template they want to work with.
This commit is contained in:
Chris Hill-Scott
2017-03-14 10:46:38 +00:00
parent 1365265fc6
commit f3c7a167df
7 changed files with 87 additions and 5 deletions

View File

@@ -0,0 +1,44 @@
(function(Modules) {
"use strict";
let normalize = (string) => string.toLowerCase().replace(/ /g,'');
let filter = ($searchBox, $targets) => () => {
let query = normalize($searchBox.val());
$targets.each(function() {
let content = $(this).text();
$(this).toggle(
normalize(content).indexOf(normalize(query)) > -1
);
});
};
Modules.LiveSearch = function() {
this.start = function(component) {
let $component = $(component);
let $searchBox = $('input', $component);
let filterFunc = filter(
$searchBox,
$($component.data('targets'))
);
$searchBox.on('keyup input', filterFunc);
filterFunc();
};
};
})(window.GOVUK.Modules);

View File

@@ -0,0 +1,16 @@
input[type=search] {
// overrides this nasty global from GOV.UK template
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.live-search {
display: none;
.js-enabled & {
display: block;
}
}

View File

@@ -58,6 +58,7 @@ $path: '/static/images/';
@import 'components/tick-cross';
@import 'components/list-entry';
@import 'components/letter';
@import 'components/live-search';
@import 'components/vendor/breadcrumbs';
@import 'components/vendor/responsive-embed';

View File

@@ -22,7 +22,7 @@ from wtforms import (
FieldList,
DateField,
SelectField)
from wtforms.fields.html5 import EmailField, TelField
from wtforms.fields.html5 import EmailField, TelField, SearchField
from wtforms.validators import (DataRequired, Email, Length, Regexp, Optional)
from app.main.validators import (Blacklist, CsvFileValidator, ValidGovEmail, NoCommasInPlaceHolders, OnlyGSMCharacters)
@@ -591,3 +591,8 @@ class ChooseTemplateType(Form):
('sms', 'Text message'),
('letter', 'Letter') if include_letters else None
])
class SearchTemplatesForm(Form):
search = SearchField('Search by name')

View File

@@ -13,7 +13,13 @@ from notifications_python_client.errors import HTTPError
from app.main import main
from app.utils import user_has_permissions, get_template, png_from_pdf
from app.main.forms import ChooseTemplateType, SMSTemplateForm, EmailTemplateForm, LetterTemplateForm
from app.main.forms import (
ChooseTemplateType,
SMSTemplateForm,
EmailTemplateForm,
LetterTemplateForm,
SearchTemplatesForm,
)
from app.main.views.send import get_example_csv_rows
from app import service_api_client, current_service, template_statistics_client
@@ -44,7 +50,8 @@ page_headings = {
def choose_template(service_id):
return render_template(
'views/templates/choose.html',
templates=service_api_client.get_service_templates(service_id)['data']
templates=service_api_client.get_service_templates(service_id)['data'],
search_form=SearchTemplatesForm(),
)

View File

@@ -1,4 +1,5 @@
{% from "components/message-count-label.html" import message_count_label %}
{% from "components/textbox.html" import textbox %}
{% extends "withnav_template.html" %}
@@ -35,7 +36,7 @@
{% else %}
<div class="grid-row">
<div class="grid-row bottom-gutter-1-2">
<div class="column-two-thirds">
<h1 class="heading-large">Templates</h1>
</div>
@@ -46,7 +47,14 @@
{% endif %}
</div>
<nav class="grid-row">
<div class="live-search" data-module="live-search" data-targets="#template-list .column-whole">
{{ textbox(
search_form.search,
width='1-1'
) }}
</div>
<nav class="grid-row" id=template-list>
{% for template in templates %}
<div class="column-whole">
<h2 class="message-name">

View File

@@ -64,6 +64,7 @@ gulp.task('javascripts', () => gulp
paths.src + 'javascripts/radioSelect.js',
paths.src + 'javascripts/updateContent.js',
paths.src + 'javascripts/listEntry.js',
paths.src + 'javascripts/liveSearch.js',
paths.src + 'javascripts/main.js'
])
.pipe(plugins.prettyerror())