diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 4b97b68b300..b82168bdd78 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -34,6 +34,8 @@ //= require admin/views/organisation-form //= require admin/views/unpublish-display-conditions +//= require content_block_manager/application + 'use strict' window.GOVUK.approveAllCookieTypes() window.GOVUK.cookie('cookies_preferences_set', 'true', { days: 365 }) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 93859945366..068bce7c472 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -49,7 +49,7 @@ $govuk-page-width: 1140px; @import "./admin/views/whats-new"; @import "./admin/views/worldwide-organisations-choose-main-office"; -@import "../../../lib/engines/content_block_manager/app/assets/stylesheets/content_block_manager/application"; +@import "./content_block_manager/application"; .app-js-only { display: none; diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 493e0c0987c..e0242f22572 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -5,3 +5,8 @@ # Add Yarn node_modules folder to the asset load path. Rails.application.config.assets.paths << Rails.root.join("node_modules") + +# Add engines to the assets load path +Dir.glob(Rails.root.join("lib/engines/**/assets/*")).each do |path| + Rails.application.config.assets.paths << path +end diff --git a/lib/engines/content_block_manager/app/assets/javascripts/content_block_manager/application.js b/lib/engines/content_block_manager/app/assets/javascripts/content_block_manager/application.js new file mode 100644 index 00000000000..d5222b5e015 --- /dev/null +++ b/lib/engines/content_block_manager/app/assets/javascripts/content_block_manager/application.js @@ -0,0 +1 @@ +//= require ./modules/copy-embed-code diff --git a/lib/engines/content_block_manager/app/assets/javascripts/content_block_manager/modules/copy-embed-code.js b/lib/engines/content_block_manager/app/assets/javascripts/content_block_manager/modules/copy-embed-code.js new file mode 100644 index 00000000000..bcd9bde1d26 --- /dev/null +++ b/lib/engines/content_block_manager/app/assets/javascripts/content_block_manager/modules/copy-embed-code.js @@ -0,0 +1,81 @@ +'use strict' +window.GOVUK = window.GOVUK || {} +window.GOVUK.Modules = window.GOVUK.Modules || {} +;(function (Modules) { + function CopyEmbedCode(module) { + this.module = module + this.copyLink = this.createLink.bind(this)() + } + + CopyEmbedCode.prototype.init = function () { + const dd = document.createElement('dd') + dd.classList.add('govuk-summary-list__actions') + dd.append(this.copyLink) + + this.module.append(dd) + } + + CopyEmbedCode.prototype.createLink = function () { + const copyLink = document.createElement('a') + copyLink.classList.add('govuk-link') + copyLink.classList.add('govuk-link__copy-link') + copyLink.setAttribute('href', '#') + copyLink.setAttribute('role', 'button') + copyLink.textContent = 'Copy code' + copyLink.addEventListener('click', this.copyCode.bind(this)) + // Handle when a keyboard user highlights the link and clicks return + copyLink.addEventListener( + 'keydown', + function (e) { + if (e.keyCode === 13) { + this.copyCode.bind(this) + } + }.bind(this) + ) + + return copyLink + } + + CopyEmbedCode.prototype.copyCode = function (e) { + e.preventDefault() + + const embedCode = this.module.dataset.embedCode + this.writeToClipboard(embedCode).then(this.copySuccess.bind(this)) + } + + CopyEmbedCode.prototype.copySuccess = function () { + const originalText = this.copyLink.textContent + this.copyLink.textContent = 'Code copied' + this.copyLink.focus() + + setTimeout(this.restoreText.bind(this, originalText), 2000) + } + + CopyEmbedCode.prototype.restoreText = function (originalText) { + this.copyLink.textContent = originalText + } + + // This is a fallback for browsers that do not support the async clipboard API + CopyEmbedCode.prototype.writeToClipboard = function (embedCode) { + return new Promise(function (resolve) { + // Create a textarea element with the embed code + const textArea = document.createElement('textarea') + textArea.value = embedCode + + document.body.appendChild(textArea) + + // Select the text in the textarea + textArea.select() + + // Copy the selected text + document.execCommand('copy') + + // Remove our textarea + document.body.removeChild(textArea) + + resolve() + }) + } + + Modules.CopyEmbedCode = CopyEmbedCode +})(window.GOVUK.Modules) diff --git a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.html.erb b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.html.erb index e9043bf0229..ac8f8efc41f 100644 --- a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.html.erb +++ b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.html.erb @@ -1,4 +1,4 @@ -<%= render "components/summary_card", { +<%= render "govuk_publishing_components/components/summary_card", { title:, rows:, summary_card_actions:, diff --git a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.rb b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.rb index 73e465872b5..4ffc0ed9361 100644 --- a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.rb +++ b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/index/summary_card_component.rb @@ -6,6 +6,7 @@ def rows { key: item[:field], value: item[:value], + data: item[:data], } end end diff --git a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/summary_list_component.rb b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/summary_list_component.rb index 76cd37676e0..c0b05d52f7e 100644 --- a/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/summary_list_component.rb +++ b/lib/engines/content_block_manager/app/components/content_block_manager/content_block/document/show/summary_list_component.rb @@ -23,6 +23,10 @@ def embed_code_item { field: "Embed code", value: content_block_document.embed_code, + data: { + module: "copy-embed-code", + "embed-code": content_block_document.embed_code, + }, } end diff --git a/lib/engines/content_block_manager/features/search_for_object.feature b/lib/engines/content_block_manager/features/search_for_object.feature index 44d12c9ece1..009ab5c60b6 100644 --- a/lib/engines/content_block_manager/features/search_for_object.feature +++ b/lib/engines/content_block_manager/features/search_for_object.feature @@ -20,6 +20,8 @@ Feature: Search for a content object | title | ministry address | | email_address | ministry@example.com | | organisation | Ministry of Example | + + Scenario: GDS Editor can filter by organisation When I visit the Content Block Manager home page Then my organisation is already selected as a filter And I should see the details for all documents from my organisation @@ -28,23 +30,36 @@ Feature: Search for a content object Then "3" content blocks are returned Scenario: GDS Editor searches for a content object by keyword in title - When I enter the keyword "example search" + When I visit the Content Block Manager home page + And I enter the keyword "example search" And I click to view results Then I should see the content block with title "example search title" returned And "1" content blocks are returned Scenario: GDS Editor searches for a content object by keyword in details - When I enter the keyword "ABC123" + When I visit the Content Block Manager home page + And I enter the keyword "ABC123" And I click to view results Then I should see the content block with title "an address" returned And "1" content blocks are returned Scenario: GDS Editor searches for a content object by block type - When I check the block type "Email address" + When I visit the Content Block Manager home page + And I select the lead organisation "All organisations" + And I check the block type "Email address" And I click to view results And "2" content blocks are returned Scenario: GDS Editor searches for a content object by lead organisation - When I select the lead organisation "Ministry of Example" + When I visit the Content Block Manager home page + And I select the lead organisation "Ministry of Example" And I click to view results And "1" content blocks are returned + + @javascript + Scenario: GDS Editor can copy embed code + When I visit the Content Block Manager home page + And I select the lead organisation "Ministry of Example" + And I click to view results + And I click to copy the embed code for the content block "ministry address" + Then the embed code should be copied to my clipboard diff --git a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb index 1994a40dabd..172ac9c42ec 100644 --- a/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb +++ b/lib/engines/content_block_manager/features/step_definitions/content_block_manager_steps.rb @@ -595,3 +595,24 @@ def click_save_and_continue Then("I should see the content block manager home page") do expect(page).to have_content("All content blocks") end + +When("I click to copy the embed code") do + find("a", text: "Copy code").click + has_text?("Code copied") + @embed_code = @content_block.document.embed_code +end + +When("I click to copy the embed code for the content block {string}") do |content_block_name| + within(".govuk-summary-card", text: content_block_name) do + find("a", text: "Copy code").click + has_text?("Code copied") + document = ContentBlockManager::ContentBlock::Document.find_by(title: content_block_name) + @embed_code = document.embed_code + end +end + +Then("the embed code should be copied to my clipboard") do + page.driver.browser.execute_cdp("Browser.grantPermissions", origin: page.server_url, permissions: %w[clipboardReadWrite]) + clip_text = page.evaluate_async_script("navigator.clipboard.readText().then(arguments[0])") + expect(clip_text).to eq(@embed_code) +end diff --git a/lib/engines/content_block_manager/features/view_object.feature b/lib/engines/content_block_manager/features/view_object.feature index 951335aebae..a8dc0739a5e 100644 --- a/lib/engines/content_block_manager/features/view_object.feature +++ b/lib/engines/content_block_manager/features/view_object.feature @@ -20,3 +20,11 @@ Feature: View a content object And I click to view the document Then I should see the dependent content listed + @javascript + Scenario: GDS Editor can copy embed code + When I visit the Content Block Manager home page + Then I should see the details for all documents + When I click to view the document + And I click to copy the embed code + Then the embed code should be copied to my clipboard + diff --git a/lib/engines/content_block_manager/spec/content_block_manager/copy-code.spec.js b/lib/engines/content_block_manager/spec/content_block_manager/copy-code.spec.js new file mode 100644 index 00000000000..a09c27a8df9 --- /dev/null +++ b/lib/engines/content_block_manager/spec/content_block_manager/copy-code.spec.js @@ -0,0 +1,72 @@ +describe('GOVUK.Modules.CopyEmbedCode', function () { + let fixture, embedCode, copyEmbedCode, copyLink, fakeTextarea + + beforeEach(function () { + embedCode = 'something' + fixture = document.createElement('div') + fixture.setAttribute('data-embed-code', embedCode) + fixture.innerHTML = ` +