hof 20.0.0-beta.8 → 20.0.0-redis-beta.32-redis-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/.github/workflows/automate-publish.yml +1 -1
  2. package/.github/workflows/automate-tag.yml +4 -4
  3. package/.nyc_output/cb764db8-e9f0-43bb-b3b1-7af57bb79bb5.json +1 -0
  4. package/.nyc_output/processinfo/cb764db8-e9f0-43bb-b3b1-7af57bb79bb5.json +1 -0
  5. package/.nyc_output/processinfo/index.json +1 -1
  6. package/README.md +329 -256
  7. package/components/index.js +2 -1
  8. package/components/notify/index.js +60 -0
  9. package/components/notify/notify.js +25 -0
  10. package/config/hof-defaults.js +2 -1
  11. package/controller/controller.js +14 -4
  12. package/frontend/template-mixins/mixins/template-mixins.js +7 -3
  13. package/frontend/template-mixins/partials/forms/checkbox-group.html +10 -1
  14. package/frontend/template-mixins/partials/forms/input-text-date.html +1 -1
  15. package/frontend/template-mixins/partials/forms/input-text-group.html +5 -3
  16. package/frontend/template-mixins/partials/forms/option-group.html +9 -0
  17. package/frontend/template-mixins/partials/forms/select.html +1 -1
  18. package/frontend/template-mixins/partials/forms/textarea-group.html +2 -2
  19. package/frontend/template-partials/views/layout.html +10 -3
  20. package/frontend/template-partials/views/partials/cookie-banner.html +1 -1
  21. package/frontend/template-partials/views/partials/form.html +2 -1
  22. package/frontend/template-partials/views/partials/warn.html +7 -0
  23. package/frontend/themes/gov-uk/client-js/index.js +3 -5
  24. package/frontend/themes/gov-uk/styles/govuk.scss +4 -0
  25. package/frontend/themes/gov-uk/styles/modules/_validation.scss +2 -2
  26. package/frontend/toolkit/assets/javascript/form-focus.js +10 -1
  27. package/frontend/toolkit/assets/javascript/progressive-reveal.js +3 -1
  28. package/frontend/toolkit/assets/javascript/validation.js +6 -1
  29. package/lib/health.js +1 -1
  30. package/lib/sessions.js +1 -1
  31. package/middleware/rate-limiter.js +3 -1
  32. package/package.json +4 -3
  33. package/sandbox/apps/sandbox/fields.js +1 -0
  34. package/sandbox/apps/sandbox/index.js +1 -5
  35. package/sandbox/apps/sandbox/translations/en/default.json +36 -15
  36. package/sandbox/assets/scss/app.scss +0 -52
  37. package/sandbox/package.json +2 -0
  38. package/sandbox/public/css/app.css +21 -6666
  39. package/sandbox/public/js/bundle.js +37 -2793
  40. package/sandbox/server.js +2 -1
  41. package/sandbox/yarn.lock +39 -564
  42. package/.nyc_output/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json +0 -1
  43. package/.nyc_output/processinfo/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json +0 -1
  44. package/.vscode/settings.json +0 -6
  45. package/frontend/govuk-template/govuk_template_generated.html +0 -104
  46. package/sandbox/.env +0 -1
@@ -5,5 +5,6 @@ module.exports = {
5
5
  clearSession: require('./clear-session'),
6
6
  date: require('./date'),
7
7
  emailer: require('./emailer'),
8
- summary: require('./summary')
8
+ summary: require('./summary'),
9
+ notify: require('./notify')
9
10
  };
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ const Notify = require('./notify');
4
+ const Hogan = require('hogan.js');
5
+ const fs = require('fs');
6
+
7
+ module.exports = config => {
8
+ const notify = new Notify(config);
9
+ config.parse = config.parse || (data => data);
10
+
11
+ if (!config.recipient) {
12
+ throw new Error('Email recipient must be defined');
13
+ }
14
+ if (typeof config.template !== 'string') {
15
+ throw new Error('Email template must be defined');
16
+ }
17
+
18
+ return superclass => class NotifyBehaviour extends superclass {
19
+ successHandler(req, res, next) {
20
+ Promise.resolve()
21
+ .then(() => {
22
+ return new Promise((resolve, reject) => {
23
+ fs.readFile(config.template, (err, template) => err ? reject(err) : resolve(template.toString('utf8')));
24
+ });
25
+ })
26
+ .then(template => {
27
+ const data = config.parse(req.sessionModel.toJSON(), req.translate);
28
+ return Hogan.compile(template).render(data);
29
+ })
30
+ .then(body => {
31
+ const settings = { body };
32
+
33
+ if (typeof config.recipient === 'function') {
34
+ settings.recipient = config.recipient(req.sessionModel.toJSON());
35
+ } else {
36
+ settings.recipient = req.sessionModel.get(config.recipient) || config.recipient;
37
+ }
38
+ if (typeof settings.recipient !== 'string' || !settings.recipient.includes('@')) {
39
+ throw new Error('hof-behaviour-emailer: invalid recipient');
40
+ }
41
+
42
+ if (typeof config.subject === 'function') {
43
+ settings.subject = config.subject(req.sessionModel.toJSON(), req.translate);
44
+ } else {
45
+ settings.subject = config.subject;
46
+ }
47
+
48
+ return settings;
49
+ })
50
+ .then(settings => {
51
+ return notify.send(settings);
52
+ })
53
+ .then(() => {
54
+ super.successHandler(req, res, next);
55
+ }, next);
56
+ }
57
+ };
58
+ };
59
+
60
+ module.exports.Notify = Notify;
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+ const NotifyClient = require('notifications-node-client').NotifyClient;
3
+ const {v4: uuidv4} = require('uuid');
4
+
5
+ module.exports = class Notify {
6
+ constructor(opts) {
7
+ const options = opts || {};
8
+ this.options = options;
9
+ this.notifyClient = new NotifyClient(options.notifyApiKey);
10
+ this.notifyTemplate = options.notifyTemplate;
11
+ }
12
+
13
+ send(email) {
14
+ const reference = uuidv4();
15
+
16
+ return this.notifyClient.sendEmail(this.notifyTemplate, email.recipient, {
17
+ personalisation: {
18
+ 'email-subject': email.subject,
19
+ 'email-body': email.body
20
+ },
21
+ reference });
22
+ }
23
+ };
24
+
25
+ module.exports.NotifyClient = NotifyClient;
@@ -27,7 +27,8 @@ const defaults = {
27
27
  ignoreMiddlewareLogs: ['/healthz'],
28
28
  redis: {
29
29
  port: process.env.REDIS_PORT || '6379',
30
- host: process.env.REDIS_HOST || '127.0.0.1'
30
+ host: process.env.REDIS_HOST || '127.0.0.1',
31
+ legacyMode: true
31
32
  },
32
33
  session: {
33
34
  ttl: process.env.SESSION_TTL || 1800,
@@ -115,6 +115,7 @@ module.exports = class Controller extends BaseController {
115
115
  title: this.getTitle(route, lookup, req.form.options.fields, res.locals),
116
116
  header: this.getHeader(route, lookup, res.locals),
117
117
  captionHeading: this.getCaptionHeading(route, lookup, res.locals),
118
+ warning: this.getWarning(route, lookup, res.locals),
118
119
  subHeading: this.getSubHeading(route, lookup, res.locals),
119
120
  intro: this.getIntro(route, lookup, res.locals),
120
121
  backLink: this.getBackLink(req, res),
@@ -143,6 +144,10 @@ module.exports = class Controller extends BaseController {
143
144
  return lookup(`pages.${route}.subHeading`, locals);
144
145
  }
145
146
 
147
+ getWarning(route, lookup, locals) {
148
+ return lookup(`pages.${route}.warning`, locals);
149
+ }
150
+
146
151
  getTitle(route, lookup, fields, locals) {
147
152
  let fieldName = '';
148
153
  if (_.size(fields)) {
@@ -166,13 +171,18 @@ module.exports = class Controller extends BaseController {
166
171
  Object.keys(req.form.errors).forEach(key => {
167
172
  if (req.form && req.form.options && req.form.options.fields) {
168
173
  const field = req.form.options.fields[key];
169
- // get first option for radios
170
- if (field.mixin === 'radio-group') {
171
- req.form.errors[key].errorLinkId = key + '-' + field.options[0];
174
+ // get first option for radios and checkbox
175
+ if (field.mixin === 'radio-group' || field.mixin === 'checkbox-group') {
176
+ // get first option for radios and checkbox where there is a toggle
177
+ if(typeof field.options[0] === 'object') {
178
+ req.form.errors[key].errorLinkId = key + '-' + field.options[0].value;
179
+ } else {
180
+ req.form.errors[key].errorLinkId = key + '-' + field.options[0];
181
+ }
172
182
  // eslint-disable-next-line brace-style
173
183
  }
174
184
  // get first field for date input control
175
- else if (field && field.controlType === 'date-input') {
185
+ else if (field && field.mixin === 'input-date') {
176
186
  req.form.errors[key].errorLinkId = key + '-day';
177
187
  } else {
178
188
  req.form.errors[key].errorLinkId = key;
@@ -215,6 +215,7 @@ module.exports = function (options) {
215
215
  child: field.child,
216
216
  isPageHeading: field.isPageHeading,
217
217
  attributes: field.attributes,
218
+ isPrefixOrSuffix: _.map(field.attributes, item => {if (item.prefix || item.suffix !== undefined) return true;}),
218
219
  renderChild: renderChild.bind(this)
219
220
  });
220
221
  }
@@ -224,6 +225,7 @@ module.exports = function (options) {
224
225
  const field = Object.assign({}, this.options.fields[key] || options.fields[key]);
225
226
  const legend = field.legend;
226
227
  const detail = field.detail;
228
+ const warningValue = 'fields.' + key + '.warning';
227
229
  let legendClassName;
228
230
  let legendValue = 'fields.' + key + '.legend';
229
231
  if (legend) {
@@ -241,6 +243,8 @@ module.exports = function (options) {
241
243
  legendClassName: legendClassName,
242
244
  role: opts.type === 'radio' ? 'radiogroup' : 'group',
243
245
  isPageHeading: field.isPageHeading,
246
+ isWarning: field.isWarning,
247
+ warning: t(warningValue),
244
248
  detail: detail ? detail : '',
245
249
  hint: conditionalTranslate(getTranslationKey(field, key, 'hint')),
246
250
  options: _.map(field.options, function (obj) {
@@ -303,7 +307,7 @@ module.exports = function (options) {
303
307
  invalid: this.errors && this.errors[key] && opts.required,
304
308
  label: t(fieldLabel || 'fields.' + key + '.label'),
305
309
  selected: selected,
306
- className: classNames(field) || 'block-label',
310
+ className: classNames(field) || 'govuk-label govuk-checkboxes__label',
307
311
  child: field.child,
308
312
  renderChild: renderChild.bind(this)
309
313
  });
@@ -444,8 +448,8 @@ module.exports = function (options) {
444
448
  parts.push(dayPart);
445
449
  }
446
450
 
447
- const monthPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-month', { pattern: '[0-9]*', min: 1, max: 12, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.month, formGroupClassName, className: classNameMonth, isRequired }));
448
- const yearPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-year', { pattern: '[0-9]*', maxlength: 4, hintId: key + '-hint', date: true, autocomplete: autocomplete.year, formGroupClassName, className: classNameYear, isRequired }));
451
+ const monthPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-month', { pattern: '[0-9]*', min: 1, max: 12, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.month, formGroupClassName, className: classNameMonth, isThisRequired }));
452
+ const yearPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-year', { pattern: '[0-9]*', maxlength: 4, hintId: key + '-hint', date: true, autocomplete: autocomplete.year, formGroupClassName, className: classNameYear, isThisRequired }));
449
453
 
450
454
  return parts.concat(monthPart, yearPart).join('\n');
451
455
  };
@@ -5,6 +5,15 @@
5
5
  {{legend}}
6
6
  {{#isPageHeading}}</h1>{{/isPageHeading}}
7
7
  </legend>
8
+ {{#isWarning}}
9
+ <div class="govuk-warning-text">
10
+ <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
11
+ <strong class="govuk-warning-text__text">
12
+ <span class="govuk-warning-text__assistive">Warning</span>
13
+ {{warning}}
14
+ </strong>
15
+ </div>
16
+ {{/isWarning}}
8
17
  {{#hint}}<div id="{{key}}-hint" class="govuk-hint">{{hint}}</div>{{/hint}}
9
18
  {{#error}}
10
19
  <p id="{{key}}-error" class="govuk-error-message">
@@ -28,7 +37,7 @@
28
37
  >
29
38
  <label class="govuk-label govuk-checkboxes__label" for="{{key}}-{{value}}">
30
39
  {{{label}}}
31
- {{#optionHint}}<div id="{{key}}-{{value}}-item-hint" class="govuk-hint govuk-radios__hint">{{optionHint}}</div>{{/optionHint}}
40
+ {{#optionHint}}<div id="{{key}}-{{value}}-item-hint" class="govuk-hint">{{optionHint}}</div>{{/optionHint}}
32
41
  </label>
33
42
  </div>
34
43
  {{#renderChild}}{{/renderChild}}
@@ -14,7 +14,7 @@
14
14
  type="{{type}}"
15
15
  name="{{id}}"
16
16
  id="{{id}}"
17
- class="govuk-input{{#className}} {{className}}{{/className}}{{#error}} invalid-input{{/error}}"
17
+ class="govuk-input{{#className}} {{className}}{{/className}}{{#error}} govuk-input--error{{/error}}"
18
18
  aria-required="{{required}}"
19
19
  {{#value}} value="{{value}}"{{/value}}
20
20
  {{#min}} min="{{min}}"{{/min}}
@@ -1,5 +1,5 @@
1
1
  <div id="{{id}}-group" class="{{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}}{{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
2
- {{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}">
2
+ {{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}{{#isPageHeading}}govuk-label--l{{/isPageHeading}}">
3
3
  {{{label}}}
4
4
  </label>
5
5
  {{#isPageHeading}}</h1>{{/isPageHeading}}
@@ -10,6 +10,7 @@
10
10
  </p>
11
11
  {{/error}}
12
12
  {{#renderChild}}{{/renderChild}}
13
+ {{#isPrefixOrSuffix}}<div class="govuk-input__wrapper">{{/isPrefixOrSuffix}}
13
14
  {{#attributes}}
14
15
  {{#prefix}}
15
16
  <div class="govuk-input__prefix" aria-hidden="true">{{prefix}}</div>
@@ -19,7 +20,7 @@
19
20
  type="{{type}}"
20
21
  name="{{id}}"
21
22
  id="{{id}}"
22
- class="{{^className}}govuk-input{{/className}}{{#className}}{{className}}{{/className}}{{#error}} invalid-input{{/error}}"
23
+ class="{{^className}}govuk-input{{/className}}{{#className}}{{className}}{{/className}}{{#error}} govuk-input--error{{/error}}"
23
24
  aria-required="{{required}}"
24
25
  {{#value}} value="{{value}}"{{/value}}
25
26
  {{#min}} min="{{min}}"{{/min}}
@@ -35,7 +36,8 @@
35
36
  >
36
37
  {{#attributes}}
37
38
  {{#suffix}}
38
- <div class="govuk-input__prefix" aria-hidden="true">{{suffix}}</div>
39
+ <div class="govuk-input__suffix" aria-hidden="true">{{suffix}}</div>
39
40
  {{/suffix}}
40
41
  {{/attributes}}
42
+ {{#isPrefixOrSuffix}}</div>{{/isPrefixOrSuffix}}
41
43
  </div>
@@ -5,6 +5,15 @@
5
5
  {{legend}}
6
6
  {{#isPageHeading}}</h1>{{/isPageHeading}}
7
7
  </legend>
8
+ {{#isWarning}}
9
+ <div class="govuk-warning-text">
10
+ <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
11
+ <strong class="govuk-warning-text__text">
12
+ <span class="govuk-warning-text__assistive">Warning</span>
13
+ {{warning}}
14
+ </strong>
15
+ </div>
16
+ {{/isWarning}}
8
17
  {{#hint}}<div id="{{key}}-hint" class="govuk-hint">{{hint}}</div>{{/hint}}
9
18
  {{#error}}<p id="{{key}}-error" class="govuk-error-message"><span class="govuk-visually-hidden">Error:</span> {{error.message}}</p>{{/error}}
10
19
  {{{detail}}}
@@ -9,7 +9,7 @@
9
9
  {{/error}}
10
10
  </label>
11
11
  {{#isPageHeading}}</h1>{{/isPageHeading}}
12
- <select id="{{id}}" class="govuk-select{{#className}} {{className}}{{/className}}{{#error}} invalid-input{{/error}}" name="{{id}}" aria-required="{{required}}">
12
+ <select id="{{id}}" class="govuk-select{{#className}} {{className}}{{/className}}{{#error}} govuk-select--error{{/error}}" name="{{id}}" aria-required="{{required}}">
13
13
  {{#options}}
14
14
  <option value="{{value}}" {{#selected}}selected{{/selected}}>{{label}}</option>
15
15
  {{/options}}
@@ -2,7 +2,7 @@
2
2
  <div class="govuk-character-count" data-module="govuk-character-count" data-maxlength="{{maxlength}}">
3
3
  {{/maxlength}}
4
4
  <div id="{{id}}-group" class="{{#compound}}form-group-compound {{/compound}}{{#formGroupClassName}}{{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
5
- {{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}">
5
+ {{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}{{#isPageHeading}}govuk-label--l{{/isPageHeading}}">
6
6
  {{{label}}}
7
7
  {{#error}}
8
8
  <p id="{{id}}-error" class="govuk-error-message">
@@ -16,7 +16,7 @@
16
16
  <textarea
17
17
  name="{{id}}"
18
18
  id="{{id}}"
19
- class="govuk-textarea{{#className}} {{className}}{{/className}} {{#maxlength}}maxlength{{/maxlength}}{{#error}} invalid-input{{/error}}"
19
+ class="govuk-textarea{{#className}} {{className}}{{/className}} {{#maxlength}}maxlength{{/maxlength}}{{#error}} govuk-input--error{{/error}}"
20
20
  aria-required="{{required}}"
21
21
  {{#maxlength}} maxlength="{{maxlength}}"{{/maxlength}}
22
22
  {{#attributes}}
@@ -44,9 +44,16 @@
44
44
  {{/gaTagId}}
45
45
  {{/cookieMessage}}
46
46
  {{$footerSupportLinks}}
47
- <li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/cookies">{{#t}}base.cookies{{/t}}</a></li>
48
- <li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/accessibility">{{#t}}base.accessibility{{/t}}</a></li>
49
- <li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/terms-and-conditions">{{#t}}base.terms{{/t}}</a></li>
47
+ <ul>
48
+ {{#footerSupportLinks}}
49
+ <li class="govuk-footer__inline-list-item"><a href="{{path}}">{{#t}}{{property}}{{/t}}</a></li>
50
+ {{/footerSupportLinks}}
51
+ {{^footerSupportLinks}}
52
+ <li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/cookies">{{#t}}base.cookies{{/t}}</a></li>
53
+ <li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/accessibility">{{#t}}base.accessibility{{/t}}</a></li>
54
+ <li class="govuk-footer__inline-list-item"><a class="govuk-footer__link" href="/terms-and-conditions">{{#t}}base.terms{{/t}}</a></li>
55
+ {{/footerSupportLinks}}
56
+ </ul>
50
57
  {{/footerSupportLinks}}
51
58
  {{$bodyEnd}}
52
59
  {{> partials-gatag}}
@@ -20,7 +20,7 @@
20
20
  </div>
21
21
  <div class="gem-c-cookie-banner__confirmation govuk-width-container" tabindex="0" hidden="" id="cookie-banner-submitted" >
22
22
  <p class="gem-c-cookie-banner__confirmation-message" role="alert">
23
- Your cookie preferences have been saved. You can <a class="govuk-link" data-module="gem-track-click" data-track-category="cookieBanner" data-track-action="Cookie banner settings clicked from confirmation" href="/student-help/cookies">change your cookie settings</a> at any time.
23
+ Your cookie preferences have been saved. You can <a class="govuk-link" data-module="gem-track-click" data-track-category="cookieBanner" data-track-action="Cookie banner settings clicked from confirmation" href="/cookies">change your cookie settings</a> at any time.
24
24
  </p>
25
25
  <div class="govuk-button-group">
26
26
  <button class="gem-c-cookie-banner__hide-button govuk-button" id="hide-cookie-banner">Hide this message</button>
@@ -1,7 +1,8 @@
1
1
  <form action="" method="POST" {{$encoding}}{{/encoding}} autocomplete="off" novalidate="true" spellcheck="false">
2
2
  {{$intro}}
3
- {{#intro}}<span class="govuk-hint" >{{intro}}</span>{{/intro}}
3
+ {{#intro}}<p>{{intro}}</p>{{/intro}}
4
4
  {{/intro}}
5
+
5
6
  {{$form}}{{/form}}
6
7
  {{#csrf-token}}
7
8
  <input type="hidden" name="x-csrf-token" value="{{csrf-token}}" />
@@ -0,0 +1,7 @@
1
+ <div class="govuk-warning-text">
2
+ <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
3
+ <strong class="govuk-warning-text__text">
4
+ <span class="govuk-warning-text__assistive">Warning</span>
5
+ {{warning}}
6
+ </strong>
7
+ </div>
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-var */
1
+ /* eslint-disable no-var, vars-on-top, no-unused-vars */
2
2
  'use strict';
3
3
 
4
4
  var toolkit = require('../../../toolkit');
@@ -9,13 +9,11 @@ var characterCount = toolkit.characterCount;
9
9
  var validation = toolkit.validation;
10
10
 
11
11
  var GOVUK = require('govuk-frontend');
12
- // eslint-disable-next-line no-unused-vars
12
+ GOVUK.initAll();
13
+ window.GOVUK = GOVUK;
13
14
  var skipToMain = require('./skip-to-main');
14
- // eslint-disable-next-line no-unused-vars
15
15
  var cookie = require('./govuk-cookies');
16
16
  var cookieSettings = require('./cookieSettings');
17
- GOVUK.initAll();
18
- window.GOVUK = GOVUK;
19
17
 
20
18
  toolkit.detailsSummary();
21
19
 
@@ -12,6 +12,10 @@ $path: "/public/images/" !default;
12
12
  // https://github.com/alphagov/govuk_elements/blob/master/packages/govuk-elements-sass/public/sass/_elements.scss
13
13
  @import "govuk-elements-sass/public/sass/elements";
14
14
 
15
+ // Govuk frontend
16
+ // https://github.com/alphagov/govuk-frontend-docs
17
+ @import "govuk-frontend";
18
+
15
19
  // Custom
16
20
  @import "base";
17
21
  @import "layout";
@@ -25,7 +25,7 @@
25
25
  .govuk-form-group--error {
26
26
  box-sizing: border-box;
27
27
  padding-left: $gutter-half - $validation-bdr-size;
28
- border-left: $validation-bdr-size-lg solid $error-colour;
28
+ //border-left: $validation-bdr-size-lg solid $error-colour;
29
29
 
30
30
  &:focus {
31
31
  outline: $focus-outline;
@@ -42,7 +42,7 @@
42
42
  margin-bottom: 0.5em;
43
43
  }
44
44
  @include bold-19;
45
- color: $error-colour;
45
+ //color: $error-colour;
46
46
  }
47
47
 
48
48
  .invalid-input,
@@ -71,11 +71,20 @@ function formFocus() {
71
71
  var labels;
72
72
  var summaries;
73
73
 
74
- if (getElementFromSummaryLink && getEditPath === 'edit') {
74
+ var editMode = getElementFromSummaryLink && getEditPath === 'edit';
75
+
76
+ if (getElementFromSummaryLink && document.getElementById(getElementFromSummaryLink) && editMode) {
75
77
  document.getElementById(getElementFromSummaryLink).focus();
78
+ }
79
+
80
+ if (getElementFromSummaryLink && document.getElementById(getElementFromSummaryLink + '-group') && editMode) {
76
81
  document.getElementById(getElementFromSummaryLink + '-group').scrollIntoView();
77
82
  }
78
83
 
84
+ if (document.getElementById(getElementFromSummaryLink + '-day') && forms.length === 1 && editMode) {
85
+ document.getElementById(getElementFromSummaryLink + '-day').focus();
86
+ }
87
+
79
88
  if (forms.length > 0) {
80
89
  labels = document.getElementsByTagName('label');
81
90
  if (labels) {
@@ -7,12 +7,14 @@ var groupBy = require('lodash').groupBy;
7
7
  var helpers = require('./helpers');
8
8
  var inputs; var groups;
9
9
  var toggleAttr = 'data-toggle';
10
- var hiddenClass = 'js-hidden';
10
+ var checkboxHiddenClass = 'govuk-checkboxes__conditional--hidden';
11
+ var radioHiddenClass = 'govuk-radios__conditional--hidden';
11
12
 
12
13
  function inputClicked(e, target) {
13
14
  target = target || helpers.target(e);
14
15
  var shown;
15
16
  each(groups[target.name], function (input) {
17
+ var hiddenClass = (input.type.match(/checkbox/)) ? checkboxHiddenClass : radioHiddenClass;
16
18
  var id = input.getAttribute('aria-controls');
17
19
  var toggle = document.getElementById(id);
18
20
  if (toggle) {
@@ -24,7 +24,12 @@ function clicked(e) {
24
24
  }
25
25
 
26
26
  if (inputs) {
27
- inputs[0].focus();
27
+ if (inputs[0].getAttribute('type') === 'hidden') {
28
+ var getVisibleElements = group.querySelectorAll('input[type=text]');
29
+ getVisibleElements[0].focus();
30
+ } else {
31
+ inputs[0].focus();
32
+ }
28
33
  }
29
34
  }
30
35
  }
package/lib/health.js CHANGED
@@ -15,7 +15,7 @@ module.exports = redis => {
15
15
 
16
16
  router.get('/readiness', healthCheck({
17
17
  test: () => {
18
- if (!redis.connected && !redis.ready) {
18
+ if (!redis.isOpen && !redis.isReady) {
19
19
  return new Error('Session store unhealthy');
20
20
  }
21
21
  return 0;
package/lib/sessions.js CHANGED
@@ -50,7 +50,7 @@ module.exports = (app, config) => {
50
50
  logger.error(e);
51
51
  });
52
52
  }
53
-
53
+ client.connect();
54
54
  const store = new RedisStore({
55
55
  client: client,
56
56
  ttl: config.session.ttl,
@@ -25,9 +25,11 @@ module.exports = (options, rateLimitType) => {
25
25
  }
26
26
 
27
27
  const closeConnection = async err => {
28
- await redisClient.quit();
28
+ await redisClient.v4.QUIT();
29
29
  return next(err);
30
30
  };
31
+ redisClient.on('error', err => logger.log('error', err));
32
+ await redisClient.connect();
31
33
 
32
34
  try {
33
35
  // fetch records of current user using IP address, returns null when no record is found
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hof",
3
3
  "description": "A bootstrap for HOF projects",
4
- "version": "20.0.0-beta.8",
4
+ "version": "20.0.0-redis-beta.32-redis-beta",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
7
7
  "author": "HomeOffice",
@@ -42,7 +42,7 @@
42
42
  "callsite": "^1.0.0",
43
43
  "chalk": "^2.0.0",
44
44
  "chokidar": "^3.4.0",
45
- "connect-redis": "^5.2.0",
45
+ "connect-redis": "^6.1.3",
46
46
  "cookie-parser": "^1.4.6",
47
47
  "cp": "^0.2.0",
48
48
  "csrf": "^3.0.2",
@@ -79,7 +79,8 @@
79
79
  "nodemailer-ses-transport": "^1.5.0",
80
80
  "nodemailer-smtp-transport": "^2.7.4",
81
81
  "nodemailer-stub-transport": "^1.1.0",
82
- "redis": "^3.1.2",
82
+ "notifications-node-client": "^5.1.1",
83
+ "redis": "^4.3.1",
83
84
  "reqres": "^3.0.1",
84
85
  "request": "^2.79.0",
85
86
  "rimraf": "^3.0.2",
@@ -21,6 +21,7 @@ module.exports = {
21
21
  isPageHeading: 'true'
22
22
  },
23
23
  'dateOfBirth': dateComponent('dateOfBirth', {
24
+ mixin: 'input-date',
24
25
  isPageHeading: 'true',
25
26
  validate: [
26
27
  'required',
@@ -30,11 +30,7 @@ module.exports = {
30
30
  },
31
31
  '/dob': {
32
32
  fields: ['dateOfBirth'],
33
- next: '/address',
34
- locals: {
35
- step: 'dob',
36
- labelClassName: 'govuk-input'
37
- }
33
+ next: '/address'
38
34
  },
39
35
  '/address': {
40
36
  fields: ['building', 'street', 'townOrCity', 'postcode'],