This replicates how we let large spreadsheets scroll horizontally.
Pro: this looks nicer and is more usable
Con: the code for this feels a bit fragile, especially the calling of
`.maintainWidth` twice, ie as many times as a it takes to get stuff to
render properly.
It’s annoying that this button moves after you click on it. It’s
happening because the API key is wrapping onto multiple lines.
This commit fixes the height of the container so that it doesn’t reflow
when it has less content in it.
Uses a bit of flexbox to vertically centre the text.
The `oninput` event is a more performant way to detect changes to a
textbox’s contents (compared to `onkeydown`, `onpaste`, etc).
It’s not supported in older browsers, but since this is a likely to be
used by platform admin users only that’s OK.
This commit improves the code that previews a hex colour when setting up
or changing an email branding.
Specifically it:
- refactors the Javascript to conform to our patterns (module pattern,
preprocessed with Gulp)
- makes the code work when there are multiple colour previews on one
page
It also does some visual prettifying, because I couldn’t help myself…
Service contact details are needed if the upload document permission is
enabled - this used to be a link but services can now choose to use a
link, email address or phone number. The form to add or change service
contact details now gives these options and validates the data according
to the type of contact details provided.
When validating phone numbers we can't use the existing validation
because we want to allow landlines too, so there is a basic check that
the phone number is the right length and doesn't include certain
characters.
We’re interested to know which services are looking at the basic view
preview (even if they’re not turning it on).
This commit logs their service IDs as events into Google Analytics.
In research we found that:
- people didn’t initially realise that the permissions expanded when the
‘admin’ option was selected
- not having all the options visible at once makes it hard to know what
permissions you are (and more importantly aren’t) giving to people
This commit makes it so that:
- the options within the ‘admin’ option are always visible
- a bit of Javascript logic makes it so you can pick ‘caseworker’ and
‘manage service’, for example (by deselecting one when you pick the
other)
This commit changes the form that the user sees when inviting or editing
another user, if the service has the ‘caseworking’ permission set.
This will allow creating a new type of user, one who only has the
`send_messages` permission, without the `view_activity` permission.
We are doing this because we think there are a number of services with a
lot of users who don’t need to see the dashboard, or the other team
members, and that we can make a simpler interface for these users.
It’s noticeable when clicking from row to row in the spreadsheet that
the page jumps around a fair bit on load because there are a couple of
Javascript-powered components.
This commit makes sure:
- the radio select component doesn’t change height when rendering for
the first time
- the scrollable table doesn’t show parts of the table that should be
hidden by overflow for a fraction of second before all the JS has
run
- the right-hand shadow on horizontally scrollable tables doesn’t fade
in on initial page load but shows at 100% opacity immediately
We weren’t calculating the height quite right; we were trying to
compensate for something that should have been compensated for in the
`stick-at-top-when-scrolling` code.
Add the 5px to the shim there is required because we’re adding it to the
element that the shim in replacing.
There were three problems with showing tables fullscreen:
- it was over-optimised for very big spreadsheets, whereas most users
will only have a few columns in their files
- it was jarring to go from full screen and back to the normal layout
- it was a bit change for existing users, where we prefer incremental
changes that make things better without disrupting people’s work
(where possible)
So this commit changes the big table to scroll horizontally in the page,
not take up the full width of the page.
From the fullscreen table it keeps:
- the shimming method to keep the horizontal scrollbar at the bottom of
the screen at all times
It introduces some more refinements to make it nicer to use:
- fixing the first column, so you always know what row you’re on
- adding shadows indicate where there is content that’s scrolled outside
the edges of the container
Two bits of context:
1. As we start dealing with letters, which have more columns, it’s more
likely that people’s spreadsheets won’t fit in our current layout.
2. We already removed the view of the template from the page that shows
row-level errors (eg bad phone number or missing personalisation) in
spreadsheets because you don’t need to know about the content of the
message in order to fix the errors.
This commit goes further by removing anything that isn’t to do with
the errors, including the normal GOV.UK header and the service’s
navigation.
This means the content can go the width of the page, which means it can
be allowed to scroll horizontally without being a usability car
crash. Which means that the layout doesn’t break with a spreadsheet that
has lots of columns.
Have seen users complaining that they got an invitation email twice.
This is probably because they clicked the button twice even though they
think they only clicked it once.
Double form submission is a common issue on web pages, and there are a
number of different ways to prevent it. I’ve chosen to do it this way
because:
- temporarily, not permanently disabling the button means that this
addresses the double clicking issue without breaking things if the
user did, really want to click the button again deliberately (for
whatever reason)
- doing it with a `data` attribute, rather than the `disabled` attribute
means that the interaction behaviour of the button doesn’t change (
`disabled` buttons can’t be focused, for example)
Google analytics lets you send:
- pageviews
- events
Page views are used by default. But sometimes you wanna count something
which isn’t the user navigating to a new page, or you wanna track
something which isn’t just what page they were looking it. This is where
events are useful.
This commit adds a small JS module that lets us fire off an event when
the presence of an element with the right data attributes are present on
the page.
See parent commit for the reason we’re doing this.
Currently our AJAX requests only work as `GET` requests. So this commit
does a bit of work to make them work as `POST` requests. This is
optional behaviour, and will only happen when the element in the page
that should be updated with AJAX has the `data-form` attribute set. It
will take the form that has the corresponding `id`, serialise it, and
use that data as the body of the post request. If not form is specified
it will not do the serialisation, and submit as a `GET` request as
before.
You might need to scroll this page quite a lot to see where a
placeholder appears in your template – especially if you have a long
email or letter.
One of the things I’m trying to stop happening so much is a lot of
scrolling back and forth. This would happen if you were scrolling down
to see the placeholder, then back up to fill in its value.
So this commit makes the textbox ‘sticky’, ie it always stays at the top
of the viewport, even when you scroll down. This lets you see the
placeholder and the textbox side by side, no matter how long the
template is.
The code to do this mostly comes from the GOV.UK Frontend Toolkit
(documented here: d9489a9870/docs/javascript.md (stick-at-top-when-scrolling)).
I had to add some extra CSS to make it look good when it overlaps the
content of the page, which the GOV.UK Frontend Toolkit implementation
doesn’t really anticipate.
We’ve seen in research a user getting stuck playing with the
scheduler. They picked a day, but then didn’t want to choose one of the
options for that day. There’s no way to do this except pick a day and
then un-pick it.
What they ended up doing was clicking the grey back button, which took
them back to the previous page, making them upload their file again.
This commit adds a ‘back’ link for the scheduler. ‘Back’ seems like
sensible naming because that’s the thing that the user tried to click,
and the UI of a link matches the thing they clicked to get into this
situation.
The visual appearance of radio and checkbox form inputs changed in
GOV.UK Elements here:
https://github.com/alphagov/govuk_elements/pull/296
This was subsequently reimplemented with different markup and no
Javascript here:
https://github.com/alphagov/govuk_elements/pull/406
This has meant making the following changes to our app:
- changing the markup in our radio/checkbox macros to match the example
markup given by GOV.UK Elements
- removing the previous Javascript file because it’s no longer needed to
make the radios appear visual selected
- making the buttons on the scheduled job picker look like links,
because the grey button style looked weird with the new radio buttons
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.
> If both sections of the page have errors and the page is submitted,
> focus moves to the mobile numbers section so screen reader users may
> not be aware of preceding errors - focus should move to a dedicated
> error summary at the top of the page.
Right now we use Javascript to focus the first error on a page (if any
errors are found). This commit adds more JS to then focus the error
summary, if there is one on the page. So this is where the focus will
rest.
It also makes some modifications to the ‘dangerous’ banner to make it
focusable, and to visually indicate that it is focused.
Fixes the height of the component until it’s loaded so that it doesn’t
causes the page to reflow while it’s rendering the buttons.
Stops the options being shown and then immediately hiding on initial
page load.
Categories before:
> Now, today, tomorrow, Friday…
Categories after:
> Now, later today, tomorrow Friday…
This reduces the ambiguity of ‘now’ vs ‘today’, and keeping the word
‘later’ suggests what this features is about.
This implementation here is a bit hacky, but it works…
The options for scheduling a job by time should be grouped by day,
because a long list of 96 options is not very usable.
On the server side, this commit generates label for the next 4 days in
a friendly format (ie today/tomorrow/Sunday/Monday)
The Javascript component for choosing a time was built in a kind of
old-school jQuery way, where it manipulated the elements on the page.
The complexity of introducing groups of options was just too much for
this pattern, because it involves storing a lot of state in the DOM.
This commit completely rewrites the JS to:
- read the initial options and groups from the HTML and store them
in the object
- use Hogan to completely re-render the UI from a series of Mustache
templates, each of which represents a state of the UI and takes the
inital options and groups
- filter the choices to show when the today/tomorrow/… buttons are
clicked
The polyfill we use for details/summary only renders the arrow if the
browser doesn’t natively support the feature.
The latest versions of Firefox _do_ now support the feature (after 5
years), but for some reason they don’t draw the arrow. So this commit
forces the arrow to be polyfilled in all browsers, and hides the browser
default one, for those browsers that do render it.
It’s weird to be on a page that says ‘2 seconds ago’ and stays stuck
there.
We don’t want to AJAX the whole page because it would get in the way of
interacting with the list of notifications.
This commit adds the venerable jQuery Timeago[1] plugin to keep the
relative times accurate and fresh.
1. http://timeago.yarp.com/
Services who are in alpha or building prototypes need a way of sending
to any email address or phone number without having to sign the MOU.
This commit adds a page where they can whitelist up to 5 email addresses
and 5 phone numbers.
It uses the ‘list entry’ UI pattern from the Digital Marketplace
frontend toolkit [1] [2] [3].
I had to do some modification:
- of the Javascript, to make it work with the GOV.UK Module pattern
- of the template to make it work with WTForms
- of the content security policy, because the list entry pattern uses
Hogan[1], which needs to use `eval()` (this should be fine if we’re
only allowing it for scripts that we serve)
- of our SASS lint config, to allow browser-targeting mixins to come
after normal rules (so that they can override them)
This commit also adds a new form class to validate and populate the two
whitelists. The validation is fairly rudimentary at the moment, and
doesn’t highlight which item in the list has the error, but it’s
probably good enough.
The list can only be updated all-at-once, this is how it’s possible to
remove items from the list without having to make multiple `POST`
requests.
1. 434ad30791/toolkit/templates/forms/list-entry.html
2. 434ad30791/toolkit/scss/forms/_list-entry.scss
3. 434ad30791/toolkit/javascripts/list-entry.js
4. http://twitter.github.io/hogan.js/
Users need to pick a time in the next 24hrs, or send a file immediately.
Rationale for this is a bit lost in time-before-holiday, but generally:
‘Now’ and ‘later’ as the inital choices makes it really clear what
this feature is about conceptually.
The choice of times is absolute, eg ‘1pm’ not ‘in 3 hours’
The pages with AJAX on were feeling quite sluggish, and it felt like
they were making the whole browser slow down.
Looking at the performance stuff in Chrome, the number of DOM nodes was
going up and up, which is weird because the number of things on the page
wasn’t changing. This was causing the page to consume more and more
memory in order to store all these nodes.
This is kinda beyond my understanding, but I tried a few things and it
looks like the browser was having a hard time garbage collecting the
temporary bits of DOM used to update the page.
By assinging these bits of DOM to variables before using them it seems
that the browser has an easier time cleaning them up.
Implements: https://github.com/alphagov/notifications-utils/pull/51
Copies the same regex.
Adds some CSS to display conditional placeholders differently to
normal placeholders (vertical rather that curved right-hand edge).
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](9d17690de5/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.
A long email message needs to be collapsed to only show the first few
lines. The problem is that we were doing this by adding a class with
Javascript, meaning that the email wasn’t being collapsed until the
script in the footer ran.
This caused a jump in the page because the browser was painting the
whole email message, then repainting it once it was collapsed.
This commit takes advantage of the `.js-enabled` class added to the
`<body>` by a script in the `<head>` of GOV.UK template.
This means that the email message is collapsed with CSS before the first
paint of the page, so no jump.
This introduces some complexity in how we determine which emails get the
expander toggle. Because they’re already collapsed we can’t get their
height and work out if they’re long enough to need collapsing.
So we need to take a copy of the message, put it off-screen, expand it,
get its height, then remove it from the DOM. Bit of a faff.
Because of this there’s still a quick flash of the toggle if you see an
email message that’s too short to need collapsing. I think this is the
lesser of two evils—very short email messages will be few and far
between in the real world.
With the change in implementation in the previous commit, any error
(eg server responds with `500`) would cause the page to not be updated
again.
This is better than the previous implementation, whereby the browser
would re-request as fast as it could until it got a successful response.
This commit handles errors by clearing the render queue if the server
returns an error. So:
- Any updates that would have been performed based on this request are
dropped
- Subsequent updates will be attempted as if it was the first load of
the page, ie after a delay of `x` seconds
The `updateContent` module updates a section of the page based on an
AJAX request.
The current implementation will poll every `x` seconds. If the server
takes a long time to respond, this results in a the browser queuing up
requests. If a particular endpoint is slow, this can result in one
client making enough requests to slow down the whole server, to the
point where it gets removed from the loadbalancer, eventually bringing
the whole site down.
This commit rewrites the module so that it queues up the render
operations, not the requests.
There is one queue per endpoint, so for
`http://example.com/endpoint.json`:
1. Queue is empty
```javascript
{
'http://example.com/endpoint.json': []
}
```
2. Inital re-render is put on the queue…
```javascript
{
'http://example.com/endpoint.json': [
function render(){…}
]
}
```
…AJAX request fires
```
GET http://example.com/endpoint.json
```
3. Every `x` seconds, another render operation is put on the queue
```javascript
{
'http://example.com/endpoint.json': [
function render(){…},
function render(){…},
function render(){…}
]
}
```
4. AJAX request returns queue is flushed by executing each queued
render function in sequence
```javascript
render(response); render(response); render(response);
```
```javascript
{
'http://example.com/endpoint.json': []
}
```
5. Repeat
This means that, at most, the AJAX requests will never fire more than
once every `x` seconds, where `x` defaults to `1.5`.