From c937d948223f84134cec839d68eaf985a982b493 Mon Sep 17 00:00:00 2001 From: Susmitha Girumala Date: Tue, 29 Sep 2020 11:13:26 -0400 Subject: [PATCH] feat: Use clipboardjs library in copy-button component --- ui/core/app/components/copy-button/index.hbs | 20 +++++- ui/core/app/components/copy-button/index.js | 72 +++++++++++++++++++ ui/core/package.json | 5 +- .../components/copy-button-test.js | 20 ++---- ui/core/translations/actions/en-us.yaml | 1 + yarn.lock | 10 ++- 6 files changed, 108 insertions(+), 20 deletions(-) diff --git a/ui/core/app/components/copy-button/index.hbs b/ui/core/app/components/copy-button/index.hbs index fb5c4b157..94dca5ce1 100644 --- a/ui/core/app/components/copy-button/index.hbs +++ b/ui/core/app/components/copy-button/index.hbs @@ -1 +1,19 @@ -{{yield}} \ No newline at end of file +{{#if this.isClipboardLibrarySupported}} + + + {{yield}} + + + + +{{else}} + {{yield}} +{{/if}} diff --git a/ui/core/app/components/copy-button/index.js b/ui/core/app/components/copy-button/index.js index 1e32d2663..33f444ed0 100644 --- a/ui/core/app/components/copy-button/index.js +++ b/ui/core/app/components/copy-button/index.js @@ -1,4 +1,76 @@ import Component from '@glimmer/component'; +import ClipboardJS from 'clipboard'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; +import { generateComponentID } from 'rose/utilities/component-auto-id'; +import { task, timeout } from 'ember-concurrency'; +import { set } from '@ember/object'; +import { bind } from '@ember/runloop'; export default class CopyButtonComponent extends Component { + + // =attributes + + id = generateComponentID(); + targetId = `copy-target-${this.id}`; + icon = 'copy-action'; + + @tracked clipboard; + + /** + * A Ember Concurrency-based task that updates copy icon to a success state + * and back after 1 second. This icon flash indicates success on + * copy to clipboard action. + * + * NOTE: tasks are sort of attributes and sort of methods, but they are not + * language-level constructs. Thus we annotate this task as if it + * is an attribute. + * @type {Task} + */ + @task(function * () { + set(this, 'icon', 'copy-success'); + yield timeout(1000); + set(this, 'icon', 'copy-action'); + }).drop() successIconTimer; + + // =methods + + /** + * Checks for ClipboardJS support. + * @return {boolean} + */ + get isClipboardLibrarySupported() { + return ClipboardJS?.isSupported(); + } + + /** + * When copy to clipboard is successful, begin timer to show success icon. + */ + onCopySuccess(clipboardEvent) { + clipboardEvent.clearSelection(); + this.successIconTimer.perform(); + } + + // =actions + + /** + * Initialize ClipboardJS library and register for it's events. + */ + @action + register() { + if(!this.clipboard) { + this.clipboard = new ClipboardJS('.copy-button'); + this.clipboard.on('success', bind(this, this.onCopySuccess)); + } + } + + /** + * Destroy ClipboardJS library instance and cancel icon timer. + */ + @action + destroy() { + this.clipboard?.destroy(); + this.successIconTimer.cancelAll(); + } + } diff --git a/ui/core/package.json b/ui/core/package.json index b5fac0049..6b6547fbd 100644 --- a/ui/core/package.json +++ b/ui/core/package.json @@ -29,6 +29,7 @@ "devDependencies": { "@babel/core": "^7.9.6", "@ember/optional-features": "^1.3.0", + "@ember/render-modifiers": "^1.0.2", "@glimmer/component": "^1.0.0", "@glimmer/tracking": "^1.0.0", "api": "*", @@ -36,6 +37,7 @@ "babel-eslint": "^10.0.3", "babel-loader": "^8.1.0", "broccoli-asset-rev": "^3.0.0", + "clipboard": "^2.0.6", "doctoc": "^1.4.0", "ember-a11y-testing": "^3.0.0", "ember-auto-import": "^1.5.3", @@ -84,8 +86,7 @@ "qunit-dom": "^1.0.0", "rose": "*", "sass": "^1.26.5", - "sass-lint": "^1.13.1", - "clipboard": "^2.0.6" + "sass-lint": "^1.13.1" }, "engines": { "node": "10.* || >= 12" diff --git a/ui/core/tests/integration/components/copy-button-test.js b/ui/core/tests/integration/components/copy-button-test.js index 428596788..be5d05a01 100644 --- a/ui/core/tests/integration/components/copy-button-test.js +++ b/ui/core/tests/integration/components/copy-button-test.js @@ -1,26 +1,14 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; +import { render, find } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; module('Integration | Component | copy-button', function(hooks) { setupRenderingTest(hooks); test('it renders', async function(assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - - await render(hbs``); - - assert.equal(this.element.textContent.trim(), ''); - - // Template block usage: - await render(hbs` - - template block text - - `); - - assert.equal(this.element.textContent.trim(), 'template block text'); + await render(hbs`text`); + assert.ok(find('.copy-button')); + assert.equal(find('.copy-target').textContent.trim(), 'text'); }); }); diff --git a/ui/core/translations/actions/en-us.yaml b/ui/core/translations/actions/en-us.yaml index 40a38941d..5598ee942 100644 --- a/ui/core/translations/actions/en-us.yaml +++ b/ui/core/translations/actions/en-us.yaml @@ -28,3 +28,4 @@ add-hosts: Add Hosts set-password: Set Password change-password: Change Password edit-form: Edit Form +copy: Copy \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e8826e237..f13b0ae16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2543,6 +2543,14 @@ ember-cli-babel "^6.16.0" ember-compatibility-helpers "^1.1.1" +"@ember/render-modifiers@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz#2e87c48db49d922ce4850d707215caaac60d8444" + integrity sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ== + dependencies: + ember-cli-babel "^7.10.0" + ember-modifier-manager-polyfill "^1.1.0" + "@ember/test-helpers@^1.7.0", "@ember/test-helpers@^1.7.1": version "1.7.1" resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.7.1.tgz#cc22a954b3b46856518f034bd492a74e0482389f" @@ -9601,7 +9609,7 @@ ember-maybe-import-regenerator@^0.1.5, ember-maybe-import-regenerator@^0.1.6: ember-cli-babel "^6.0.0-beta.4" regenerator-runtime "^0.9.5" -ember-modifier-manager-polyfill@^1.2.0: +ember-modifier-manager-polyfill@^1.1.0, ember-modifier-manager-polyfill@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda" integrity sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA==