From 30f5175d4a282bc78047b8f48c9b6b9ecad40e20 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 13:02:01 +0200 Subject: [PATCH 01/12] initial copy to clipboard functionality for the concept page --- resource/css/skosmos.css | 24 +++++++++++++----------- resource/js/copy-to-clipboard.js | 26 ++++++++++++++++++++++++++ src/view/concept-card.inc | 16 +++++++++++----- src/view/scripts.inc | 3 +++ 4 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 resource/js/copy-to-clipboard.js diff --git a/resource/css/skosmos.css b/resource/css/skosmos.css index 11bdfc72f..951d08977 100644 --- a/resource/css/skosmos.css +++ b/resource/css/skosmos.css @@ -85,13 +85,6 @@ body { margin: 0 5px; } - #main-container.termpage .fa-copy { - color: var(--vocab-text); - font-size: 30px; - position: relative; - bottom: -3px; - } - #main-container.searchpage .fa-arrow-right, #main-container.searchpage-multi-vocab .fa-arrow-right { color: var(--vocab-text); font-size: 12px; @@ -706,12 +699,21 @@ body { float: left; } - .copy-clipboard { - border: none; - font-size: 20px; + #copy-preflabel .fa-copy { + color: var(--vocab-text); + font-size: 30px; + position: relative; + bottom: -3px; + } + + #copy-uri .fa-copy { + color: var(--vocab-text); + position: relative; + bottom: 3px; + left: -0.6rem; } - .copy-clipboard:active, .copy-clipboard:focus, .copy-clipboard:active:focus { + .copy-clipboard, .copy-clipboard:active, .copy-clipboard:focus, .copy-clipboard:active:focus { border: none; } diff --git a/resource/js/copy-to-clipboard.js b/resource/js/copy-to-clipboard.js new file mode 100644 index 000000000..94cf98bf7 --- /dev/null +++ b/resource/js/copy-to-clipboard.js @@ -0,0 +1,26 @@ +// function for copying the content from a specific element (by id) to the clipboard +async function copyToClipboard (id) { + const copyElem = document.getElementById(id) + const sel = window.getSelection() + const range = document.createRange() + range.selectNodeContents(copyElem) + sel.removeAllRanges() + sel.addRange(range) + + try { + await navigator.clipboard.writeText(copyElem.innerText) + } catch (err) { + console.log('Failed to copy text to clipboard: ', err) + } +} + +// register the copyToClipboard function as event an handler for the copy buttons +const copyPrefElem = document.getElementById('copy-preflabel') +if (copyPrefElem) { + copyPrefElem.addEventListener('click', () => copyToClipboard('concept-preflabel')) +} + +const copyUriElem = document.getElementById('copy-uri') +if (copyUriElem) { + copyUriElem.addEventListener('click', () => copyToClipboard('concept-uri')) +} diff --git a/src/view/concept-card.inc b/src/view/concept-card.inc index e5c63d355..fdc829428 100644 --- a/src/view/concept-card.inc +++ b/src/view/concept-card.inc @@ -28,12 +28,12 @@ {% endif %}
-
{{ "skos:prefLabel" | trans }}
+
{{ "skos:prefLabel" | trans }}
-

{{ concept.label }}

-
@@ -87,7 +87,13 @@ {% endif %}

URI

- +
+ {{ concept.uri }} + +
diff --git a/src/view/scripts.inc b/src/view/scripts.inc index e13951fc7..20898a77a 100644 --- a/src/view/scripts.inc +++ b/src/view/scripts.inc @@ -73,3 +73,6 @@ const SKOSMOS = { + + + From 23e24513c12bc41cdb0bf361a3bb4ee9e6336bf3 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 13:06:56 +0200 Subject: [PATCH 02/12] add translations for "Copy to clipboard" text. Fixes #926 --- resource/translations/skosmos_en.po | 3 +++ resource/translations/skosmos_fi.po | 3 +++ resource/translations/skosmos_sv.po | 3 +++ 3 files changed, 9 insertions(+) diff --git a/resource/translations/skosmos_en.po b/resource/translations/skosmos_en.po index 27ec9f661..b546794a7 100644 --- a/resource/translations/skosmos_en.po +++ b/resource/translations/skosmos_en.po @@ -879,3 +879,6 @@ msgstr "Information" msgid "Breadcrumbs" msgstr "Breadcrumbs" + +msgid "Copy to clipboard" +msgstr "Copy to clipboard" diff --git a/resource/translations/skosmos_fi.po b/resource/translations/skosmos_fi.po index f35146357..b8840bebd 100644 --- a/resource/translations/skosmos_fi.po +++ b/resource/translations/skosmos_fi.po @@ -888,3 +888,6 @@ msgstr "Tietoja" msgid "Breadcrumbs" msgstr "Murupolut" + +msgid "Copy to clipboard" +msgstr "Kopioi leikepöydälle" diff --git a/resource/translations/skosmos_sv.po b/resource/translations/skosmos_sv.po index 86c6f55d5..77befd524 100644 --- a/resource/translations/skosmos_sv.po +++ b/resource/translations/skosmos_sv.po @@ -887,3 +887,6 @@ msgstr "Information" msgid "Breadcrumbs" msgstr "Brödsmulor" + +msgid "Copy to clipboard" +msgstr "Kopiera till urklipp" From d1115fff93b6b332e7af765dbfb8dce1544927b4 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 14:08:32 +0200 Subject: [PATCH 03/12] add Cypress tests for copy to clipboard functionality --- tests/cypress/template/concept.cy.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/cypress/template/concept.cy.js b/tests/cypress/template/concept.cy.js index 7d54bf0d3..94f3e65cb 100644 --- a/tests/cypress/template/concept.cy.js +++ b/tests/cypress/template/concept.cy.js @@ -95,6 +95,13 @@ describe('Concept page', () => { // check the concept prefLabel cy.get('#concept-heading h1').invoke('text').should('equal', 'music research') }) + it('concept preflabel can be copied to clipboard', () => { + cy.visit('/yso/en/page/p21685') // go to "music research" concept page + + cy.get('#copy-preflabel').click() + + cy.window().its('navigator.clipboard').invoke('readText').then((result) => {}).should('equal', 'music research'); + }) it('contains concept type', () => { cy.visit('/yso/en/page/p21685') // go to "music research" concept page @@ -219,6 +226,13 @@ describe('Concept page', () => { // check the broader concept cy.get('#concept-uri').invoke('text').should('equal', 'http://www.yso.fi/onto/yso/p21685') }) + it('concept URI can be copied to clipboard', () => { + cy.visit('/yso/en/page/p21685') // go to "music research" concept page + + cy.get('#copy-uri').click() + + cy.window().its('navigator.clipboard').invoke('readText').then((result) => {}).should('equal', 'http://www.yso.fi/onto/yso/p21685'); + }) it('contains created & modified times (English)', () => { cy.visit('/yso/en/page/p21685') // go to "music research" concept page (English) From 07be6445392cb8f76524c902608402f44c986ae0 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 14:09:41 +0200 Subject: [PATCH 04/12] remove copy to clipboard icon from search result page (not necessary) --- resource/css/skosmos.css | 5 ----- src/view/search-results.inc | 1 - 2 files changed, 6 deletions(-) diff --git a/resource/css/skosmos.css b/resource/css/skosmos.css index 951d08977..e5a84f411 100644 --- a/resource/css/skosmos.css +++ b/resource/css/skosmos.css @@ -98,11 +98,6 @@ body { text-align: center; } - #main-container.searchpage .fa-copy, #main-container.searchpage-multi-vocab .fa-copy { - position: relative; - bottom: 5px; - } - .fa-magnifying-glass { color: var(--search-button-text); font-size: 22px; diff --git a/src/view/search-results.inc b/src/view/search-results.inc index 3be138dc2..3d7e4faa2 100644 --- a/src/view/search-results.inc +++ b/src/view/search-results.inc @@ -103,7 +103,6 @@
  • URI {{ concept.uri }} -
  • {%~ endif ~%} From 7cdc87fbc5eb019e977f12b5df3448583b08f10b Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 16:48:46 +0200 Subject: [PATCH 05/12] avoid sonarqube warnings about returning Promise --- resource/js/copy-to-clipboard.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/resource/js/copy-to-clipboard.js b/resource/js/copy-to-clipboard.js index 94cf98bf7..14f3dfb6a 100644 --- a/resource/js/copy-to-clipboard.js +++ b/resource/js/copy-to-clipboard.js @@ -17,10 +17,14 @@ async function copyToClipboard (id) { // register the copyToClipboard function as event an handler for the copy buttons const copyPrefElem = document.getElementById('copy-preflabel') if (copyPrefElem) { - copyPrefElem.addEventListener('click', () => copyToClipboard('concept-preflabel')) + copyPrefElem.addEventListener('click', async () => { + await copyToClipboard('concept-preflabel') + }) } const copyUriElem = document.getElementById('copy-uri') if (copyUriElem) { - copyUriElem.addEventListener('click', () => copyToClipboard('concept-uri')) + copyUriElem.addEventListener('click', async () => { + await copyToClipboard('concept-uri') + }) } From 4ec2b98151e37cb5404a0987f4e7a3f13f993942 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 17:00:06 +0200 Subject: [PATCH 06/12] more fun with async/await --- resource/js/copy-to-clipboard.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/resource/js/copy-to-clipboard.js b/resource/js/copy-to-clipboard.js index 14f3dfb6a..1b314ea6b 100644 --- a/resource/js/copy-to-clipboard.js +++ b/resource/js/copy-to-clipboard.js @@ -17,14 +17,18 @@ async function copyToClipboard (id) { // register the copyToClipboard function as event an handler for the copy buttons const copyPrefElem = document.getElementById('copy-preflabel') if (copyPrefElem) { - copyPrefElem.addEventListener('click', async () => { - await copyToClipboard('concept-preflabel') + copyPrefElem.addEventListener('click', () => { + (async () => { + await copyToClipboard('concept-preflabel') + })() }) } const copyUriElem = document.getElementById('copy-uri') if (copyUriElem) { - copyUriElem.addEventListener('click', async () => { - await copyToClipboard('concept-uri') + copyUriElem.addEventListener('click', () => { + (async () => { + await copyToClipboard('concept-preflabel') + })() }) } From 396932feb918c909f003cd51d3da73d5422d26d4 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Wed, 31 Jan 2024 17:12:30 +0200 Subject: [PATCH 07/12] simplify JS code, avoiding async/await proliferation --- resource/js/copy-to-clipboard.js | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/resource/js/copy-to-clipboard.js b/resource/js/copy-to-clipboard.js index 1b314ea6b..fafaf29cd 100644 --- a/resource/js/copy-to-clipboard.js +++ b/resource/js/copy-to-clipboard.js @@ -1,5 +1,5 @@ // function for copying the content from a specific element (by id) to the clipboard -async function copyToClipboard (id) { +function copyToClipboard (id) { const copyElem = document.getElementById(id) const sel = window.getSelection() const range = document.createRange() @@ -7,28 +7,17 @@ async function copyToClipboard (id) { sel.removeAllRanges() sel.addRange(range) - try { - await navigator.clipboard.writeText(copyElem.innerText) - } catch (err) { - console.log('Failed to copy text to clipboard: ', err) - } + navigator.clipboard.writeText(copyElem.innerText).catch((err) => + console.error('Failed to copy text to clipboard: ', err)) } // register the copyToClipboard function as event an handler for the copy buttons const copyPrefElem = document.getElementById('copy-preflabel') if (copyPrefElem) { - copyPrefElem.addEventListener('click', () => { - (async () => { - await copyToClipboard('concept-preflabel') - })() - }) + copyPrefElem.addEventListener('click', () => copyToClipboard('concept-preflabel')) } const copyUriElem = document.getElementById('copy-uri') if (copyUriElem) { - copyUriElem.addEventListener('click', () => { - (async () => { - await copyToClipboard('concept-preflabel') - })() - }) + copyUriElem.addEventListener('click', () => copyToClipboard('concept-uri')) } From 893e1f05e08021f6e4ecd9d140816f59a808372c Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Thu, 1 Feb 2024 13:56:22 +0200 Subject: [PATCH 08/12] register copy to clipboard event handlers also after partial page loads --- resource/js/copy-to-clipboard.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/resource/js/copy-to-clipboard.js b/resource/js/copy-to-clipboard.js index fafaf29cd..e666ec9f7 100644 --- a/resource/js/copy-to-clipboard.js +++ b/resource/js/copy-to-clipboard.js @@ -11,13 +11,20 @@ function copyToClipboard (id) { console.error('Failed to copy text to clipboard: ', err)) } -// register the copyToClipboard function as event an handler for the copy buttons -const copyPrefElem = document.getElementById('copy-preflabel') -if (copyPrefElem) { - copyPrefElem.addEventListener('click', () => copyToClipboard('concept-preflabel')) -} +function registerCopyToClipboardEvents () { + const copyPrefElem = document.getElementById('copy-preflabel') + if (copyPrefElem) { + copyPrefElem.addEventListener('click', () => copyToClipboard('concept-preflabel')) + } -const copyUriElem = document.getElementById('copy-uri') -if (copyUriElem) { - copyUriElem.addEventListener('click', () => copyToClipboard('concept-uri')) + const copyUriElem = document.getElementById('copy-uri') + if (copyUriElem) { + copyUriElem.addEventListener('click', () => copyToClipboard('concept-uri')) + } } + +// register the copyToClipboard function as event an handler for the copy buttons +registerCopyToClipboardEvents() + +// re-register the event handlers after partial page loads +document.addEventListener('loadConceptPage', registerCopyToClipboardEvents) From 404633e58964bdb21d214920e41218adbf1e75bc Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Thu, 1 Feb 2024 14:19:40 +0200 Subject: [PATCH 09/12] make prefLabel and URI selectable using single click --- src/view/concept-card.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/view/concept-card.inc b/src/view/concept-card.inc index fdc829428..a79549254 100644 --- a/src/view/concept-card.inc +++ b/src/view/concept-card.inc @@ -28,9 +28,9 @@ {% endif %}
    -
    {{ "skos:prefLabel" | trans }}
    +
    {{ "skos:prefLabel" | trans }}
    -

    {{ concept.label }}

    +

    {{ concept.label }}

    diff --git a/src/view/scripts.inc b/src/view/scripts.inc index 20898a77a..deeac7cee 100644 --- a/src/view/scripts.inc +++ b/src/view/scripts.inc @@ -24,7 +24,7 @@ const SKOSMOS = { {%- if request.plugins.callbacks ~%} "pluginCallbacks": [{% for function in request.plugins.callbacks %}{% if not loop.first %}, {% endif %}"{{ function }}"{% endfor %}], {%- endif ~%} - "language_strings" :{ "fi": { "fi": "suomi", + "language_strings": { "fi": { "fi": "suomi", "en": "englanti", "se": "pohjoissaame", "sv": "ruotsi", From 864c4af02d42f1c233aa7965498fb5851003c2e2 Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Thu, 1 Feb 2024 14:49:52 +0200 Subject: [PATCH 11/12] better comments for Cypress tests --- tests/cypress/template/concept.cy.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/cypress/template/concept.cy.js b/tests/cypress/template/concept.cy.js index 94f3e65cb..573c45b56 100644 --- a/tests/cypress/template/concept.cy.js +++ b/tests/cypress/template/concept.cy.js @@ -98,8 +98,13 @@ describe('Concept page', () => { it('concept preflabel can be copied to clipboard', () => { cy.visit('/yso/en/page/p21685') // go to "music research" concept page + // click the copy to clipboard button next to the prefLabel cy.get('#copy-preflabel').click() + // check that the clipboard now contains "music research" + // NOTE: This test may fail when running Cypress interactively in a browser. + // The reason is browser security policies for accessing the clipboard. + // If that happens, make sure the browser window has focus and re-run the test. cy.window().its('navigator.clipboard').invoke('readText').then((result) => {}).should('equal', 'music research'); }) it('contains concept type', () => { @@ -229,8 +234,13 @@ describe('Concept page', () => { it('concept URI can be copied to clipboard', () => { cy.visit('/yso/en/page/p21685') // go to "music research" concept page + // click the copy to clipboard button next to the URI cy.get('#copy-uri').click() + // check that the clipboard now contains "http://www.yso.fi/onto/yso/p21685" + // NOTE: This test may fail when running Cypress interactively in a browser. + // The reason is browser security policies for accessing the clipboard. + // If that happens, make sure the browser window has focus and re-run the test. cy.window().its('navigator.clipboard').invoke('readText').then((result) => {}).should('equal', 'http://www.yso.fi/onto/yso/p21685'); }) it('contains created & modified times (English)', () => { From f5ee24c160b288f91ed4ff4df81df221dd6c446c Mon Sep 17 00:00:00 2001 From: Osma Suominen Date: Thu, 1 Feb 2024 15:58:11 +0200 Subject: [PATCH 12/12] add focus indicator for copy to clipboard buttons --- resource/css/skosmos.css | 12 ++++++------ src/view/concept-card.inc | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/resource/css/skosmos.css b/resource/css/skosmos.css index 32bf48e46..fda786a1f 100644 --- a/resource/css/skosmos.css +++ b/resource/css/skosmos.css @@ -694,7 +694,7 @@ body { display: inline; } - #copy-preflabel .fa-copy { + #copy-preflabel { color: var(--vocab-text); font-size: 30px; position: relative; @@ -702,15 +702,15 @@ body { left: 5px; } - #copy-uri .fa-copy { + #copy-uri { color: var(--vocab-text); position: relative; - bottom: 3px; - left: -0.6rem; + bottom: 4px; } - .copy-clipboard, .copy-clipboard:active, .copy-clipboard:focus, .copy-clipboard:active:focus { - border: none; + .copy-clipboard:focus { + border: 1px solid var(--vocab-text); + border-radius: 3px; } .property ul, .property li { diff --git a/src/view/concept-card.inc b/src/view/concept-card.inc index 8e4299572..79029c766 100644 --- a/src/view/concept-card.inc +++ b/src/view/concept-card.inc @@ -30,8 +30,9 @@
    {{ "skos:prefLabel" | trans }}
    -

    {{ concept.label }}

    - @@ -88,8 +89,9 @@

    URI

    - {{ concept.uri }} -