-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2443 from alphagov/js-enhancement-single-page-not…
…if-button Get single page notification button from personalisation API on load
- Loading branch information
Showing
9 changed files
with
276 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
48 changes: 48 additions & 0 deletions
48
...ets/javascripts/govuk_publishing_components/components/single-page-notification-button.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* global XMLHttpRequest */ | ||
window.GOVUK = window.GOVUK || {} | ||
window.GOVUK.Modules = window.GOVUK.Modules || {}; | ||
|
||
(function (Modules) { | ||
function SinglePageNotificationButton ($module) { | ||
this.$module = $module | ||
this.basePath = this.$module.querySelector('input[name="base_path"]').value | ||
this.buttonLocation = this.$module.getAttribute('data-button-location') | ||
|
||
this.personalisationEndpoint = '/api/personalisation/check-email-subscription?base_path=' + this.basePath | ||
// This attribute is passed through to the personalisation API to ensure the updated button has the same button_location for analytics | ||
if (this.buttonLocation) this.personalisationEndpoint += '&button_location=' + this.buttonLocation | ||
} | ||
|
||
SinglePageNotificationButton.prototype.init = function () { | ||
var xhr = new XMLHttpRequest() | ||
xhr.open('GET', this.personalisationEndpoint, true) | ||
|
||
xhr.onreadystatechange = function () { | ||
if (xhr.readyState === 4 && xhr.status === 200) { | ||
var responseText = xhr.responseText | ||
// if response text exists and is JSON parse-able, parse the response and get the button html | ||
if (responseText && this.responseIsJSON(responseText)) { | ||
var newButton = JSON.parse(responseText).button_html | ||
var html = document.createElement('div') | ||
html.innerHTML = newButton | ||
// test that the html returned contains the button component; if yes, swap the button for the updated version | ||
var responseHasButton = html.querySelector('form.gem-c-single-page-notification-button .gem-c-single-page-notification-button__submit') | ||
if (responseHasButton) { | ||
this.$module.outerHTML = newButton | ||
} | ||
} | ||
} | ||
}.bind(this) | ||
xhr.send() | ||
} | ||
|
||
SinglePageNotificationButton.prototype.responseIsJSON = function (string) { | ||
try { | ||
JSON.parse(string) | ||
} catch (e) { | ||
return false | ||
} | ||
return true | ||
} | ||
Modules.SinglePageNotificationButton = SinglePageNotificationButton | ||
})(window.GOVUK.Modules) |
20 changes: 7 additions & 13 deletions
20
app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,17 @@ | ||
<% | ||
page ||= '' | ||
data_attributes ||= {} | ||
base_path ||= nil | ||
local_assigns[:margin_bottom] ||= 3 | ||
already_subscribed ||= false | ||
text ||= already_subscribed ? t('components.single_page_notification_button.unsubscribe_text') : t('components.single_page_notification_button.subscribe_text') | ||
|
||
component_helper = GovukPublishingComponents::Presenters::SinglePageNotificationButtonHelper.new(local_assigns) | ||
shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns) | ||
|
||
wrapper_classes = %w(gem-c-single-page-notification-button govuk-!-display-none-print) | ||
wrapper_classes << shared_helper.get_margin_bottom | ||
classes = "govuk-body-s gem-c-single-page-notification-button__submit" | ||
%> | ||
<% button_text = capture do %> | ||
<svg class="gem-c-single-page-notification-button__icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 459.334 459.334"><path fill="currentColor" d="M177.216 404.514c-.001.12-.009.239-.009.359 0 30.078 24.383 54.461 54.461 54.461s54.461-24.383 54.461-54.461c0-.12-.008-.239-.009-.359H175.216zM403.549 336.438l-49.015-72.002v-89.83c0-60.581-43.144-111.079-100.381-122.459V24.485C254.152 10.963 243.19 0 229.667 0s-24.485 10.963-24.485 24.485v27.663c-57.237 11.381-100.381 61.879-100.381 122.459v89.83l-49.015 72.002a24.76 24.76 0 0 0 20.468 38.693H383.08a24.761 24.761 0 0 0 20.469-38.694z"/></svg><%= text %> | ||
<svg class="gem-c-single-page-notification-button__icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" height="18" width="18" viewBox="0 0 459.334 459.334"><path fill="currentColor" d="M177.216 404.514c-.001.12-.009.239-.009.359 0 30.078 24.383 54.461 54.461 54.461s54.461-24.383 54.461-54.461c0-.12-.008-.239-.009-.359H175.216zM403.549 336.438l-49.015-72.002v-89.83c0-60.581-43.144-111.079-100.381-122.459V24.485C254.152 10.963 243.19 0 229.667 0s-24.485 10.963-24.485 24.485v27.663c-57.237 11.381-100.381 61.879-100.381 122.459v89.83l-49.015 72.002a24.76 24.76 0 0 0 20.468 38.693H383.08a24.761 24.761 0 0 0 20.469-38.694z"/></svg><%= component_helper.button_text %> | ||
<% end %> | ||
<%= tag.form class: wrapper_classes, action: "/email/subscriptions/single-page/new", method: "POST", data: data_attributes do %> | ||
<input type="hidden" name="base_path" value="<%= base_path %>"> | ||
<%= tag.form class: wrapper_classes, action: "/email/subscriptions/single-page/new", method: "POST", data: component_helper.data do %> | ||
<input type="hidden" name="base_path" value="<%= component_helper.base_path %>"> | ||
<%= content_tag(:button, button_text, { | ||
class: classes, | ||
class: "govuk-body-s gem-c-single-page-notification-button__submit", | ||
type: "submit", | ||
}) %> | ||
<% end if base_path.presence %> | ||
<% end if component_helper.base_path %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
module GovukPublishingComponents | ||
module Presenters | ||
class SinglePageNotificationButtonHelper | ||
attr_reader :already_subscribed, :data_attributes, :base_path, :js_enhancement, :button_type, :button_location | ||
|
||
def initialize(local_assigns) | ||
@local_assigns = local_assigns | ||
@data_attributes = @local_assigns[:data_attributes] || {} | ||
@js_enhancement = @local_assigns[:js_enhancement] || false | ||
@already_subscribed = @local_assigns[:already_subscribed] || false | ||
@base_path = @local_assigns[:base_path] || nil | ||
@button_location = button_location_is_valid? ? @local_assigns[:button_location] : nil | ||
@button_type = @local_assigns[:already_subscribed] ? "Unsubscribe" : "Subscribe" | ||
end | ||
|
||
def data | ||
module_names = %w[gem-track-click] | ||
module_names << "single-page-notification-button" if js_enhancement | ||
|
||
@data_attributes[:label] = base_path | ||
# data-action for tracking should have the format of e.g. "Unsubscribe-button-top", or "Subscribe-button-bottom" | ||
# when button_location is not present data-action will fall back to "Unsubscribe-button"/"Subscribe-button" | ||
@data_attributes[:action] = [button_type, "button", button_location].compact.join("-") | ||
@data_attributes[:module] = module_names.join(" ") | ||
@data_attributes[:category] = "Single-page-notification-button" | ||
# This attribute is passed through to the personalisation API to ensure when a new button is returned from the API, it has the same button_location | ||
@data_attributes[:button_location] = button_location | ||
@data_attributes | ||
end | ||
|
||
def button_location_is_valid? | ||
%w[bottom top].include? @local_assigns[:button_location] | ||
end | ||
|
||
def button_text | ||
@already_subscribed ? I18n.t("components.single_page_notification_button.unsubscribe_text") : I18n.t("components.single_page_notification_button.subscribe_text") | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
spec/javascripts/components/single-page-notification-button-spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* eslint-env jasmine */ | ||
/* global GOVUK */ | ||
|
||
describe('Single page notification component', function () { | ||
var FIXTURE | ||
|
||
beforeEach(function () { | ||
FIXTURE = | ||
'<form class="gem-c-single-page-notification-button old-button-for-test" action="/email/subscriptions/single-page/new" method="POST" data-module="single-page-notification-button">' + | ||
'<input type="hidden" name="base_path" value="/current-page-path">' + | ||
'<button class="gem-c-single-page-notification-button__submit" type="submit">Get emails about this page</button>' + | ||
'</form>' | ||
window.setFixtures(FIXTURE) | ||
jasmine.Ajax.install() | ||
}) | ||
|
||
afterEach(function () { | ||
jasmine.Ajax.uninstall() | ||
}) | ||
|
||
it('calls the personalisation API on load', function () { | ||
initButton() | ||
var request = jasmine.Ajax.requests.mostRecent() | ||
expect(request.url).toBe('/api/personalisation/check-email-subscription?base_path=/current-page-path') | ||
expect(request.method).toBe('GET') | ||
}) | ||
|
||
it('includes button_location in the call to the personalisation API when button_location is specified', function () { | ||
FIXTURE = | ||
'<form class="gem-c-single-page-notification-button old-button-for-test" action="/email/subscriptions/single-page/new" method="POST" data-module="single-page-notification-button" data-button-location="top">' + | ||
'<input type="hidden" name="base_path" value="/current-page-path">' + | ||
'<button class="gem-c-single-page-notification-button__submit" type="submit">Get emails about this page</button>' + | ||
'</form>' | ||
window.setFixtures(FIXTURE) | ||
|
||
initButton() | ||
var request = jasmine.Ajax.requests.mostRecent() | ||
expect(request.url).toBe('/api/personalisation/check-email-subscription?base_path=/current-page-path&button_location=top') | ||
expect(request.method).toBe('GET') | ||
}) | ||
|
||
it('replaces the button when the API returns button html', function () { | ||
initButton() | ||
|
||
jasmine.Ajax.requests.mostRecent().respondWith({ | ||
status: 200, | ||
contentType: 'application/json', | ||
responseText: '{\n "base_path": "/current-page-path",\n "active": true,\n "button_html": "<form class=\\"gem-c-single-page-notification-button new-button-for-test\\" action=\\"/email/subscriptions/single-page/new\\" method=\\"POST\\">\\n <input type=\\"hidden\\" name=\\"base_path\\" value=\\"/current-page-path\\">\\n <button class=\\"gem-c-single-page-notification-button__submit\\" type=\\"submit\\">Stop getting emails about this page\\n</button>\\n</form>"\n}' | ||
}) | ||
|
||
var button = document.querySelector('form.gem-c-single-page-notification-button.new-button-for-test button') | ||
expect(button).toHaveText('Stop getting emails about this page') | ||
}) | ||
|
||
it('should remain unchanged if the response is not JSON', function () { | ||
var responseText = 'I am not JSON, actually' | ||
initButton() | ||
|
||
jasmine.Ajax.requests.mostRecent().respondWith({ | ||
status: 200, | ||
contentType: 'application/json', | ||
responseText: responseText | ||
}) | ||
|
||
var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test button') | ||
expect(button).toHaveText('Get emails about this page') | ||
expect(GOVUK.Modules.SinglePageNotificationButton.prototype.responseIsJSON(responseText)).toBe(false) | ||
}) | ||
|
||
it('should remain unchanged if response text is empty', function () { | ||
var responseText = '' | ||
initButton() | ||
|
||
jasmine.Ajax.requests.mostRecent().respondWith({ | ||
status: 200, | ||
contentType: 'application/json', | ||
responseText: responseText | ||
}) | ||
|
||
var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test button') | ||
expect(button).toHaveText('Get emails about this page') | ||
expect(GOVUK.Modules.SinglePageNotificationButton.prototype.responseIsJSON(responseText)).toBe(false) | ||
}) | ||
|
||
it('should remain unchanged if the endpoint fails', function () { | ||
initButton() | ||
|
||
jasmine.Ajax.requests.mostRecent().respondWith({ | ||
status: 500, | ||
contentType: 'text/plain', | ||
responseText: '' | ||
}) | ||
|
||
var button = document.querySelector('form.gem-c-single-page-notification-button.old-button-for-test button') | ||
expect(button).toHaveText('Get emails about this page') | ||
}) | ||
|
||
function initButton () { | ||
var element = document.querySelector('[data-module=single-page-notification-button]') | ||
new GOVUK.Modules.SinglePageNotificationButton(element).init() | ||
} | ||
}) |