diff --git a/mock/location/find.json b/mock/location/find.json index ebb39e74f..29727b31c 100644 --- a/mock/location/find.json +++ b/mock/location/find.json @@ -1,11 +1,17 @@ { "name": "London", "center": [ -0.12623600661754608, 51.500152587890625 ], - "bbox": [ - -1.0282469032939199, - 51.1557550552987, - 0.8240108759451693, - 51.880039887087904 + "bbox2k": [ + -1.03198533837149, + 51.1534935075975, + 0.8275523144418941, + 51.88222730734423 + ], + "bbox10k": [ + -1.1484905162767916, + 51.0815544369866, + 0.9440574923471953, + 51.9541663063661 ], "address": "London, London", "isEngland": { "is_england": true }, diff --git a/package-lock.json b/package-lock.json index ab3bbc9bc..e13158d3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "flood-app", - "version": "3.13.0", + "version": "3.14.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9dddf0edf..9032ee3f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flood-app", - "version": "3.13.0", + "version": "3.14.0", "description": "Flood risk app", "main": "index.js", "repository": "github:defra/flood-app", diff --git a/release-docs/beta-3.14.0.txt b/release-docs/beta-3.14.0.txt new file mode 100644 index 000000000..94f8ab048 --- /dev/null +++ b/release-docs/beta-3.14.0.txt @@ -0,0 +1,39 @@ +# Service refresh release 3.14.0 Tuesday 10th August 2021 + +# Tickets + +https://eaflood.atlassian.net/projects/FSR/versions/15493/tab/release-report-all-issues + + +## Release notes taken from Jira + +# Release notes - FIS Service Refresh - Version Release 7 + +### Bug + +[FSR-397] (https://eaflood.atlassian.net/browse/FSR-397) Prod issue - share links not working in live as expected + +### Story + +[FSR-310] (https://eaflood.atlassian.net/browse/FSR-310) Amendments to surveys on Beta service + +[FSR-332] (https://eaflood.atlassian.net/browse/FSR-332) Ability to download .csv output for river/sea/groundwater page + +[FSR-333] (https://eaflood.atlassian.net/browse/FSR-333) Accessibility amendments following from DAC review + +[FSR-334] (https://eaflood.atlassian.net/browse/FSR-334) Amendments to river/coastal/groundwater station page to meet accessibility + +[FSR-335] (https://eaflood.atlassian.net/browse/FSR-335) Amendments to river/sea/groundwater list page to meet accessibility + +[FSR-352] (https://eaflood.atlassian.net/browse/FSR-352) Amendments to navigation links on Beta service + +[FSR-353] (https://eaflood.atlassian.net/browse/FSR-353) Amendment to Outlook regional view + +[FSR-399] (https://eaflood.atlassian.net/browse/FSR-399) Accessibility - removing back button logic from the Beta + + +# Webops Instructions + +Execute job: LFW_{stage}_04_UPDATE_FLOOD_APP_AND_SERVICE_PIPELINE + +Confirm with developers that deployment was successful. diff --git a/server/models/views/find-location.js b/server/models/views/find-location.js index 58eaeeda7..5106a9a05 100644 --- a/server/models/views/find-location.js +++ b/server/models/views/find-location.js @@ -19,6 +19,11 @@ class ViewModel { this.locationInput = { label: { + text: 'Where do you want to check?', + classes: 'govuk-label--l', + isPageHeading: true + }, + hint: { text: 'Town, city or postcode in England' }, id: 'location', diff --git a/server/models/views/location.js b/server/models/views/location.js index 77207352d..1fbde5c32 100644 --- a/server/models/views/location.js +++ b/server/models/views/location.js @@ -20,7 +20,7 @@ class ViewModel { metaDescription: `Nearby flood alerts and warnings; latest river and sea levels and flood risk advice for residents living in the ${title} area.`, floodFisUrl, dateFormatted: 'Up to date as of ' + moment.tz('Europe/London').format('h:mma') + ' on ' + moment.tz('Europe/London').format('D MMMM YYYY'), - feedback: true, + feedback: false, dataError }) diff --git a/server/models/views/national.js b/server/models/views/national.js index dd15464e0..77ca33579 100644 --- a/server/models/views/national.js +++ b/server/models/views/national.js @@ -23,7 +23,7 @@ class ViewModel { highestSeverityId: floods.highestSeverityId, dateFormatted: `${moment().tz(tz).format('h:mma')} on ${moment().tz(tz).format('D MMMM YYYY')}`, dateUTC: moment().tz(tz).format(), - feedback: true, + feedback: false, hasWarningsRemoved: floods._groups[3].name === 4 && floods._groups[3].count > 0, bingMaps: bingKeyMaps, outlookTimestamp: `${formatDate(outlook._timestampOutlook, 'h:mma')} on ${formatDate(outlook._timestampOutlook, 'D MMMM YYYY')}`, diff --git a/server/models/views/station.js b/server/models/views/station.js index 575e23a5e..1b6d6ddab 100644 --- a/server/models/views/station.js +++ b/server/models/views/station.js @@ -25,7 +25,7 @@ class ViewModel { */ Object.assign(this, { - feedback: true, + feedback: false, bingMaps: config.bingKeyMaps }) // Group warnings/alerts by severity level diff --git a/server/models/views/target-area.js b/server/models/views/target-area.js index 8778ad84f..e994bdee1 100644 --- a/server/models/views/target-area.js +++ b/server/models/views/target-area.js @@ -62,7 +62,7 @@ class ViewModel { parentAreaAlert: parentAreaAlert, areaDescription: areaDescription, targetArea: area.code, - feedback: true, + feedback: false, mapTitle, bingMaps: bingKeyMaps }, options) diff --git a/server/plugins/error-pages.js b/server/plugins/error-pages.js index 061e698d8..23e9fcec6 100644 --- a/server/plugins/error-pages.js +++ b/server/plugins/error-pages.js @@ -20,14 +20,17 @@ module.exports = { return h.view('404').code(404) } + // gets captured in pm2 log file, details sent to error file below request.log('error', { statusCode: statusCode, - data: response.data, situation: response.message }) - // Normally a joi request query param validation error - if (statusCode === 400) { + // gets captured in pm2 error file + console.error(response) + + // 400 && params input is joi error + if (statusCode === 400 && response.message === 'Invalid request params input') { return h.view('404').code(404) } diff --git a/server/plugins/router.js b/server/plugins/router.js index 293d10460..16a1392ba 100644 --- a/server/plugins/router.js +++ b/server/plugins/router.js @@ -26,7 +26,9 @@ const routes = [].concat( require('../routes/privacy-notice'), require('../routes/status'), require('../routes/stations-overview'), - require('../routes/about-levels') + require('../routes/about-levels'), + require('../routes/error'), + require('../routes/station-csv') ) module.exports = { diff --git a/server/routes/error.js b/server/routes/error.js new file mode 100644 index 000000000..c7fe14e19 --- /dev/null +++ b/server/routes/error.js @@ -0,0 +1,7 @@ +const floodService = require('../services/flood') + +module.exports = { + method: 'GET', + path: '/error', + handler: () => floodService.getError() +} diff --git a/server/routes/station-csv.js b/server/routes/station-csv.js new file mode 100644 index 000000000..ca0e258c9 --- /dev/null +++ b/server/routes/station-csv.js @@ -0,0 +1,98 @@ +const floodService = require('../services/flood') +const moment = require('moment-timezone') + +module.exports = { + method: 'GET', + path: '/station-csv/{id}/{direction?}', + handler: async (request, h) => { + const { id } = request.params + let { direction } = request.params + + direction = direction === 'downstream' ? 'd' : 'u' + + const station = await floodService.getStationById(id, direction) + + const stationName = station.external_name.replace(/\s/g, '-') + + const [telemetry, thresholds] = await Promise.all([ + floodService.getStationTelemetry(id, direction), + floodService.getStationForecastThresholds(id) + ]) + + this.telemetry = telemetry + + this.telemetry.forEach(function (item) { + item.type = 'observed' + item.ts = moment.utc(item.ts).format() + }) + + // Forecast station + if (thresholds.length) { + const values = await floodService.getStationForecastData(station.wiski_id) + + const forecast = values.SetofValues[0].Value + + const forecastData = forecast.map(item => { + const itemDate = item.$.date + const itemTime = item.$.time + const date = moment(`${itemDate} ${itemTime}`).format('YYYY-MM-DDTHH:mm') + 'Z' + return { ts: date, _: item._, type: 'forecast' } + }) + + // Truncate forecast data to be 36 hours from forecast creation + const forecastStart = moment(this.telemetry[0].ts) + + this.truncateDate = moment(forecastStart).add(36, 'hours') + + forecastData.forEach(function (value) { + value.ts = moment(value.ts) + + if (value.ts.isBefore(forecastStart) || value.ts.isAfter(this.truncateDate)) { + return + } + value.ts = moment.utc(value.ts).format() + + this.telemetry.push(value) + }, this) + } + + this.telemetry.sort(function (a, b) { + return new Date(a.ts) - new Date(b.ts) + }) + + if (thresholds.length) { + this.csvString = [ + [ + 'Timestamp (UTC)', + 'Height (m)', + 'Type(observed/forecast)' + ], + ...this.telemetry.map(item => [ + item.ts, + item._, + item.type + ]) + ] + .map(e => e.join(',')) + .join('\n') + } else { + this.csvString = [ + [ + 'Timestamp (UTC)', + 'Height (m)' + ], + ...this.telemetry.map(item => [ + item.ts, + item._ + ]) + ] + .map(e => e.join(',')) + .join('\n') + } + + const response = h.response(this.csvString) + response.type('text/csv') + response.header('Content-disposition', `attachment; filename=${stationName}-height-data.csv`) + return response + } +} diff --git a/server/services/flood.js b/server/services/flood.js index a9aeca78c..0cd80d885 100644 --- a/server/services/flood.js +++ b/server/services/flood.js @@ -193,5 +193,9 @@ module.exports = { getStationsByRadius (x, y, rad) { const param3 = rad ? `/${rad}` : '' return util.getJson(`${serviceUrl}/stations-by-radius/${x}/${y}${param3}`) + }, + + getError () { + return util.getJson(`${serviceUrl}/error`) } } diff --git a/server/src/js/components/toggle-list-display.js b/server/src/js/components/toggle-list-display.js index 026ddffdb..030eb8d1e 100644 --- a/server/src/js/components/toggle-list-display.js +++ b/server/src/js/components/toggle-list-display.js @@ -15,7 +15,6 @@ const ToggleListDisplay = (container, options) => { const toggleDisplay = () => { // Toggle Button button.innerText = `${isExpanded ? 'Hide' : 'Show'} ${options.btnText}` - button.setAttribute('aria-expanded', isExpanded) // Toggle list forEach(items, (item) => { item.style.display = isExpanded ? 'block' : 'none' diff --git a/server/src/js/core.js b/server/src/js/core.js index 013be6878..c65fd7d93 100755 --- a/server/src/js/core.js +++ b/server/src/js/core.js @@ -46,20 +46,14 @@ window.flood = { const v = window.location.search.match(new RegExp('(?:[?&]' + name + '=)([^&]+)')) return v ? v[1] : null }, - addBrowserBackButton: () => { - const container = document.getElementById('browserBackContainer') - if (container) { - const hyperlink = document.createElement('a') - hyperlink.href = document.referrer - hyperlink.href = hyperlink.pathname + hyperlink.search - hyperlink.innerText = 'Back' - hyperlink.className = 'govuk-back-link govuk-!-margin-bottom-7 govuk-!-margin-right-2' - hyperlink.addEventListener('click', function (e) { - e.preventDefault() - window.history.back() - }) - container.appendChild(hyperlink) - } + getCookie: (name) => { + const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)') + return v ? v[2] : null + }, + setCookie: (name, value, days) => { + const d = new Date() + d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * days) + document.cookie = name + '=' + value + ';path=/;expires=' + d.toGMTString() } } } diff --git a/server/src/js/pages/alerts-and-warnings.js b/server/src/js/pages/alerts-and-warnings.js index 9cf27768a..4077b7f1d 100644 --- a/server/src/js/pages/alerts-and-warnings.js +++ b/server/src/js/pages/alerts-and-warnings.js @@ -7,9 +7,6 @@ import '../components/map/layers' import '../components/map/container' import '../components/map/live' -// Add browser back button -window.flood.utils.addBrowserBackButton() - if (document.getElementById('map')) { // Create LiveMap window.flood.maps.createLiveMap('map', { diff --git a/server/src/js/pages/find-location.js b/server/src/js/pages/find-location.js deleted file mode 100644 index c631733fa..000000000 --- a/server/src/js/pages/find-location.js +++ /dev/null @@ -1,2 +0,0 @@ -// Add browser back button -window.flood.utils.addBrowserBackButton() diff --git a/server/src/js/pages/impacts.js b/server/src/js/pages/impacts.js index 6b27bf444..1fd52dfad 100644 --- a/server/src/js/pages/impacts.js +++ b/server/src/js/pages/impacts.js @@ -6,6 +6,3 @@ import '../components/map/styles' import '../components/map/layers' import '../components/map/container' import '../components/map/live' - -// Add browser back button -window.flood.utils.addBrowserBackButton() diff --git a/server/src/js/pages/location.js b/server/src/js/pages/location.js index 02119712d..fed0884d9 100644 --- a/server/src/js/pages/location.js +++ b/server/src/js/pages/location.js @@ -8,9 +8,6 @@ import '../components/map/container' import '../components/map/live' import '../components/map/outlook' -// Add browser back button -window.flood.utils.addBrowserBackButton() - // Create LiveMap if (document.getElementById('map')) { window.flood.maps.createLiveMap('map', { diff --git a/server/src/js/pages/river-and-sea-levels.js b/server/src/js/pages/river-and-sea-levels.js index e151d8fcd..f36735481 100644 --- a/server/src/js/pages/river-and-sea-levels.js +++ b/server/src/js/pages/river-and-sea-levels.js @@ -9,9 +9,6 @@ import '../components/map/live' import '../components/filter' import '../components/top-link' -// Add browser back button -window.flood.utils.addBrowserBackButton() - // Create LiveMap if (document.getElementById('map')) { window.flood.maps.createLiveMap('map', { diff --git a/server/src/js/pages/station.js b/server/src/js/pages/station.js index 7bceea899..9e3b853ff 100644 --- a/server/src/js/pages/station.js +++ b/server/src/js/pages/station.js @@ -8,8 +8,7 @@ import '../components/map/layers' import '../components/map/container' import '../components/map/live' import '../components/toggle-list-display' -// Add browser back button -window.flood.utils.addBrowserBackButton() + // Create LiveMap window.flood.maps.createLiveMap('map', { btnText: 'View map', @@ -61,7 +60,7 @@ if (chart) { // Add threshold buttons Array.from(document.querySelectorAll('.defra-flood-impact-list__value')).forEach(value => { const button = document.createElement('button') - button.innerHTML = 'Show on chart' + button.innerHTML = 'Show on chart (Visual only)' button.className = 'defra-button-text-s' button.addEventListener('click', function (e) { lineChart.addThreshold({ diff --git a/server/src/js/pages/target-area.js b/server/src/js/pages/target-area.js index 6166acdb8..e995e9a5f 100644 --- a/server/src/js/pages/target-area.js +++ b/server/src/js/pages/target-area.js @@ -7,9 +7,6 @@ import '../components/map/layers' import '../components/map/container' import '../components/map/live' -// Add browser back button -window.flood.utils.addBrowserBackButton() - // Create LiveMap window.flood.maps.createLiveMap('map', { btnText: `View map of the flood ${window.flood.model.area.code.slice(4, 5).toLowerCase() === 'w' ? 'warning' : 'alert'} area`, diff --git a/server/src/sass/application.scss b/server/src/sass/application.scss index 16ab7d08f..9b8064d02 100644 --- a/server/src/sass/application.scss +++ b/server/src/sass/application.scss @@ -57,6 +57,7 @@ $govuk-breakpoints: ( @import "components/context-footer"; @import "components/feedback"; @import "components/top-link"; +@import "components/flood-location-link"; @import "components/toggle-list-display"; @import "components/social"; diff --git a/server/src/sass/components/_flood-list.scss b/server/src/sass/components/_flood-list.scss index c34d2181d..aebdef231 100644 --- a/server/src/sass/components/_flood-list.scss +++ b/server/src/sass/components/_flood-list.scss @@ -14,6 +14,7 @@ margin: 0px; } &__group { + padding-top:0px; border-bottom:1px solid govuk-colour('black'); &:last-child { border:none; @@ -24,9 +25,10 @@ margin-top: 20px; margin-bottom: 5px; @include govuk-font($size: 24, $weight: bold); - span { + & + p { @include govuk-font($size: 19); - display:block; + margin-top: -5px; + margin-bottom: 0px; } } &__title-column { diff --git a/server/src/sass/components/_flood-location-link.scss b/server/src/sass/components/_flood-location-link.scss new file mode 100644 index 000000000..9cd14332b --- /dev/null +++ b/server/src/sass/components/_flood-location-link.scss @@ -0,0 +1,8 @@ +.defra-flood-location-link { + @extend .govuk-back-link; + padding-left: 0px; + &:before { + border: 0px; + display: none; + } +} \ No newline at end of file diff --git a/server/src/sass/components/_flood-tabs.scss b/server/src/sass/components/_flood-tabs.scss index b9f317858..48f2680c4 100644 --- a/server/src/sass/components/_flood-tabs.scss +++ b/server/src/sass/components/_flood-tabs.scss @@ -20,7 +20,11 @@ display: none; } .govuk-tabs__title { - @include defra-visually-hidden(); + display: none; + @include mq ($from: tablet) { + display: block; + @include defra-visually-hidden(); + } } border-bottom:1px solid $govuk-border-colour; margin-bottom:10px; diff --git a/server/src/sass/components/_related-items.scss b/server/src/sass/components/_related-items.scss index 6b3d35cf7..33ffd6a39 100755 --- a/server/src/sass/components/_related-items.scss +++ b/server/src/sass/components/_related-items.scss @@ -1,6 +1,10 @@ .defra-related-items { border-top: 2px solid govuk-colour("blue"); padding-top: govuk-spacing(3); + margin-top: 20px; + @include mq ($from: tablet) { + margin-top: 0px; + } } .defra-related-items .govuk-list > li { diff --git a/server/src/sass/objects/_buttons.scss b/server/src/sass/objects/_buttons.scss index ca8befb12..c69ff1f41 100644 --- a/server/src/sass/objects/_buttons.scss +++ b/server/src/sass/objects/_buttons.scss @@ -11,7 +11,6 @@ top:-1px; width:13px; height:15px; - background: transparent; background-image: svg-url(''); background-color:transparent; background-size:13px 15px; @@ -73,13 +72,9 @@ top: 3px; } } - &:hover:before { + &:hover:not(:active):not(:focus):before { background-image: svg-url(''); } - &:focus:before, - &:active:before { - background-image: svg-url(''); - } &-s { @extend .defra-button-map; padding-left:17px; @@ -90,14 +85,9 @@ } &-s:before { top:0px; - background-size:12px 16px; - height:16px; - width:12px; - @include mq ($from: tablet) { - background-size:13.5px 18px; - height:18px; - width:13.5px; - } + background-size:13.5px 18px; + height:18px; + width:13.5px; } span { display: inline-block; @@ -114,3 +104,43 @@ } } +// Download button +.defra-button-download { + @extend .defra-button-text; + position:relative; + display:inline-block; + padding-left:21px; + &:before { + content: ""; + position: absolute; + top:0px; + left:1px; + background-image: svg-url(''); + background-color:transparent; + background-size:13px 17px; + background-repeat: no-repeat; + background-position: top left; + height:17px; + width:13px; + @include mq ($from: tablet) { + top: 1px; + } + } + &:hover:before { + background-image: svg-url(''); + } + &:focus:before, + &:active:before { + background-image: svg-url(''); + } + &-s { + @extend .defra-button-download; + @include govuk-font($size: 16); + } + &-s:before { + top:0px; + @include mq ($from: tablet) { + top: 1px; + } + } +} diff --git a/server/views/about-levels.html b/server/views/about-levels.html index b9bc60f71..425f39a03 100644 --- a/server/views/about-levels.html +++ b/server/views/about-levels.html @@ -2,8 +2,6 @@ {% block content %} {% set metaNoIndex = true %} -{% include "partials/back-button.html" %} -
Low, normal and high are shown when the latest level is below, within or above this range.
{{ group.severity.subTitle }}
Today there's a {{ model.tabs.dailyRisk[0] | lower }} risk of flooding.
- {% for messageId, sources in model.tabs.tab1 %} - {% if loop.first %}{% endif %} - {% include "partials/outlook-region-messages.html" %} - {% if loop.last %}
{% endif %} - {% endfor %} + {% for messageId, sources in model.tabs.tab1 %} + {% if messageId !== '1-i2-l2' %} + {% if loop.first %}{% endif %} + {% include "partials/outlook-region-messages.html" %} + {% if loop.last %}
{% endif %} + {% endif %} + {% endfor %} {% else %} @@ -61,11 +63,13 @@On {{ model.tabs.dayName[1] }} the risk of flooding {{ model.tabs.trend[1] }} {{ model.tabs.dailyRisk[1] | lower }}.
- {% for messageId, sources in model.tabs.tab2 %} - {% if loop.first %}{% endif %} - {% include "partials/outlook-region-messages.html" %} - {% if loop.last %}
{% endif %} - {% endfor %} + {% for messageId, sources in model.tabs.tab2 %} + {% if messageId !== '1-i2-l2' %} + {% if loop.first %}{% endif %} + {% include "partials/outlook-region-messages.html" %} + {% if loop.last %}
{% endif %} + {% endif %} + {% endfor %} {% else %} @@ -82,12 +86,14 @@On {{ model.tabs.dayName[dayNum - 1] }} the risk of flooding {{ model.tabs.trend[dayNum - 1]}} {{ model.tabs.dailyRisk[dayNum - 1] | lower }}.
- {% for messageId, sources in day %} - {% if loop.first %}{% endif %} - {% include "partials/outlook-region-messages.html" %} - {% if loop.last %}
{% endif %} - {% endfor %} - + + {% for messageId, sources in day %} + {% if messageId !== '1-i2-l2' %} + {% if loop.first %}{% endif %} + {% include "partials/outlook-region-messages.html" %} + {% if loop.last %}
{% endif %} + {% endif %} + {% endfor %} {% endfor %} {% else %} diff --git a/server/views/partials/related-content.html b/server/views/partials/related-content.html index 05fd269e4..84b0f048c 100644 --- a/server/views/partials/related-content.html +++ b/server/views/partials/related-content.html @@ -1,4 +1,4 @@ -You may be able to get financial aid for flood recovery. Apply to your local council.
{{ model.subtitle }} Show all levels
- {% endif %} -{{ model.subtitle }} Show all levels
+ {% endif %} +Showing levels within 5 miles of {{ model.placeDescription }}. Show all levels
+Showing levels within 5 miles of {{ model.placeDescription }}. Show all levels
Showing levels within 5 miles of {{ model.originalStation.external_name }}. Show all levels
+Showing levels within 5 miles of {{ model.originalStation.external_name }}. Show all levels