ui: Renames CopyButtonFeedback to CopyButton and use it everywhere (#7834)
* ui: Renames CopyButtonFeedback to CopyButton and use it everywhere * Uncapitalize output * Remove the ability to set the contents via an attr, and.. ..change the attribute for the string that gets copied to be called 'value' so it feels like HTML
This commit is contained in:
parent
df1ae18a41
commit
1ddffb4162
|
@ -1,15 +0,0 @@
|
|||
<FeedbackDialog @type="inline">
|
||||
<BlockSlot @name="action" as |success error|>
|
||||
<CopyButton @success={{action success}} @error={{action error}} @clipboardText={{copy}} @title={{concat "Copy " name " to the clipboard"}}>{{#if hasBlock }}{{yield}}{{else}}{{value}}{{/if}}</CopyButton>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="success" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Copied {{name}}!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="error" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Sorry, something went wrong!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</FeedbackDialog>
|
|
@ -1,5 +0,0 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
## CopyButton
|
||||
|
||||
```handlebars
|
||||
{{! inline }}
|
||||
<CopyButton
|
||||
@value={{stringToCopy}}
|
||||
@name="Thing"
|
||||
/>
|
||||
|
||||
<CopyButton
|
||||
@value={{stringToCopy}}
|
||||
@name="Thing"
|
||||
>
|
||||
Copy me!
|
||||
</CopyButton>
|
||||
```
|
||||
|
||||
### Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `value` | `String` | | The string to be copied to the clipboard on click |
|
||||
| `name` | `String` | | The 'Name' of the string to be copied. Mainly used for giving feedback to the user |
|
||||
|
||||
This component renders a simple button, when clicked copies the value (the `@value` attribute) to the users clipboard. A simple piece of feedback is given to the user in the form of a tooltip. When used inline an empty button is rendered.
|
||||
|
||||
### See
|
||||
|
||||
- [Component Source Code](./index.js)
|
||||
- [Template Source Code](./index.hbs)
|
||||
|
||||
---
|
|
@ -1,2 +1,17 @@
|
|||
{{! this overriding template makes sure you can add button:empty's }}
|
||||
{{~yield~}}
|
||||
<FeedbackDialog @type="inline">
|
||||
<BlockSlot @name="action" as |success error|>
|
||||
<Ref @target={{this}} @name="success" @value={{success}} />
|
||||
<Ref @target={{this}} @name="error" @value={{error}} />
|
||||
<button id={{guid}} title={{concat "Copy " name " to the clipboard"}} ...attributes type="button" class="copy-btn" data-clipboard-text={{value}}>{{~yield~}}</button>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="success" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Copied {{name}}!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="error" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Sorry, something went wrong!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</FeedbackDialog>
|
||||
|
|
|
@ -1,38 +1,29 @@
|
|||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
import WithListeners from 'consul-ui/mixins/with-listeners';
|
||||
|
||||
export default Component.extend(WithListeners, {
|
||||
export default Component.extend({
|
||||
clipboard: service('clipboard/os'),
|
||||
tagName: 'button',
|
||||
classNames: ['copy-btn'],
|
||||
buttonType: 'button',
|
||||
disabled: false,
|
||||
error: function() {},
|
||||
success: function() {},
|
||||
attributeBindings: [
|
||||
'clipboardText:data-clipboard-text',
|
||||
'clipboardTarget:data-clipboard-target',
|
||||
'clipboardAction:data-clipboard-action',
|
||||
'buttonType:type',
|
||||
'disabled',
|
||||
'aria-label',
|
||||
'title',
|
||||
],
|
||||
delegateClickEvent: true,
|
||||
|
||||
dom: service('dom'),
|
||||
tagName: '',
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.guid = this.dom.guid(this);
|
||||
this._listeners = this.dom.listeners();
|
||||
},
|
||||
willDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
this._listeners.remove();
|
||||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
const clipboard = this.clipboard.execute(
|
||||
this.delegateClickEvent ? `#${this.elementId}` : this.element
|
||||
);
|
||||
['success', 'error'].map(event => {
|
||||
return this.listen(clipboard, event, () => {
|
||||
if (!this.disabled) {
|
||||
this[event](...arguments);
|
||||
}
|
||||
});
|
||||
const component = this;
|
||||
this._listeners.add(this.clipboard.execute(`#${this.guid}`), {
|
||||
success: function() {
|
||||
component.success(...arguments);
|
||||
},
|
||||
error: function() {
|
||||
component.error(...arguments);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -37,21 +37,7 @@
|
|||
<dt>Output</dt>
|
||||
<dd>
|
||||
<pre><code>{{item.Output}}</code></pre>
|
||||
<FeedbackDialog @type="inline">
|
||||
<BlockSlot @name="action" as |success error|>
|
||||
<CopyButton @success={{action success}} @error={{action error}} @clipboardText={{item.Output}} @title="copy output to clipboard" />
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="success" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Copied output!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="error" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Sorry, something went wrong!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</FeedbackDialog>
|
||||
<CopyButton @value={{item.Output}} @name="output" />
|
||||
</dd>
|
||||
{{/if}}
|
||||
</dl>
|
||||
|
|
|
@ -41,11 +41,11 @@
|
|||
/* this is only for pseudo tooltips be want to avoid */
|
||||
/* specifying pseudo in this file */
|
||||
%tooltip::after {
|
||||
bottom: calc(100% - 7px);
|
||||
bottom: calc(100% - 8px);
|
||||
}
|
||||
%tooltip-bottom::before {
|
||||
bottom: auto;
|
||||
top: calc(100% + 7px);
|
||||
top: calc(100% + 8px);
|
||||
}
|
||||
%tooltip-bottom::after {
|
||||
bottom: -12px;
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
%tooltip-bubble,
|
||||
%tooltip-tail {
|
||||
%tooltip-bubble {
|
||||
color: $white;
|
||||
background-color: $gray-500;
|
||||
background-color: $gray-700;
|
||||
}
|
||||
%tooltip-tail {
|
||||
background-color: $transparent;
|
||||
border-color: $transparent;
|
||||
border-top-color: $gray-700;
|
||||
border-bottom-color: $gray-700;
|
||||
}
|
||||
|
||||
/* borders here are used to draw a triangle in CSS */
|
||||
/* the are not actual borders */
|
||||
/* they are not actual borders */
|
||||
|
||||
%tooltip-tail {
|
||||
background-color: transparent !important;
|
||||
border-left: 9px solid transparent;
|
||||
border-right: 9px solid transparent;
|
||||
|
||||
border-top: 18px solid $gray-500;
|
||||
border-style: solid;
|
||||
border-bottom-width: 0;
|
||||
border-top-width: 18px;
|
||||
border-left-width: 9px;
|
||||
border-right-width: 9px;
|
||||
}
|
||||
%tooltip-bottom::after {
|
||||
border-top: 0;
|
||||
border-bottom: 18px solid $gray-500;
|
||||
border-top-width: 0;
|
||||
border-bottom-width: 18px;
|
||||
}
|
||||
%tooltip-bubble {
|
||||
border-radius: $decor-radius-200;
|
||||
/* this isn't quite like the values in structure */
|
||||
/* but this looks closer visually */
|
||||
/* TODO: try and get this closer to structure */
|
||||
box-shadow: $decor-elevation-400;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
.actions .with-feedback p::after {
|
||||
bottom: auto;
|
||||
top: -13px !important;
|
||||
border-bottom: 18px solid $gray-800;
|
||||
border-top: 0;
|
||||
border-bottom-width: 18px;
|
||||
border-top-width: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,23 +18,9 @@
|
|||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
{{#if (not create) }}
|
||||
<FeedbackDialog @type="inline">
|
||||
<BlockSlot @name="action" as |success error|>
|
||||
<CopyButton @success={{action success}} @error={{action error}} @clipboardText={{item.ID}} @title="copy token ID to clipboard">
|
||||
Copy token ID
|
||||
</CopyButton>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="success" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Copied token ID!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="error" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Sorry, something went wrong!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</FeedbackDialog>
|
||||
<CopyButton @value={{item.ID}} @name="token ID">
|
||||
Copy token ID
|
||||
</CopyButton>
|
||||
<button type="button" {{ action "clone" item }}>Clone token</button>
|
||||
<ConfirmationDialog @message="Are you sure you want to use this ACL token?">
|
||||
<BlockSlot @name="action" as |confirm|>
|
||||
|
|
|
@ -70,11 +70,11 @@
|
|||
<dl>
|
||||
<dt>AccessorID</dt>
|
||||
<dd>
|
||||
<CopyButtonFeedback @title="Copy AccessorID to the clipboard" @copy={{item.AccessorID}} @name="AccessorID" /> {{item.AccessorID}}
|
||||
<CopyButton @value={{item.AccessorID}} @name="AccessorID" /> {{item.AccessorID}}
|
||||
</dd>
|
||||
<dt>Token</dt>
|
||||
<dd>
|
||||
<CopyButtonFeedback @title="Copy SecretID to the clipboard" @copy={{item.SecretID}} @name="Token" /> <SecretButton>{{item.SecretID}}</SecretButton>
|
||||
<CopyButton @value={{item.SecretID}} @name="Token" /> <SecretButton>{{item.SecretID}}</SecretButton>
|
||||
</dd>
|
||||
{{#if (and (not (token/is-legacy item)) (not create))}}
|
||||
<dt>Scope</dt>
|
||||
|
|
|
@ -31,23 +31,9 @@
|
|||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
{{#if (not create) }}
|
||||
<FeedbackDialog @type="inline">
|
||||
<BlockSlot @name="action" as |success error|>
|
||||
<CopyButton @success={{action success}} @error={{action error}} @clipboardText={{item.ID}} @title="copy UUID to clipboard">
|
||||
Copy UUID
|
||||
</CopyButton>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="success" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Copied UUID!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="error" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Sorry, something went wrong!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</FeedbackDialog>
|
||||
<CopyButton @value={{item.ID}} @name="UUID">
|
||||
Copy UUID
|
||||
</CopyButton>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
|
|
|
@ -28,23 +28,7 @@
|
|||
}}/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<FeedbackDialog @type="inline">
|
||||
<BlockSlot @name="action" as |success error|>
|
||||
<CopyButton @success={{action success}} @error={{action error}} @clipboardText={{item.Address}} @title="copy IP address to clipboard">
|
||||
{{item.Address}}
|
||||
</CopyButton>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="success" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Copied IP Address!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="error" as |transition|>
|
||||
<p class={{transition}}>
|
||||
Sorry, something went wrong!
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</FeedbackDialog>
|
||||
<CopyButton @value={{item.Address}} @name="Address">{{item.Address}}</CopyButton>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
{{outlet}}
|
||||
|
|
|
@ -32,9 +32,9 @@
|
|||
{{#if (gt item.LocalBindPort 0)}}
|
||||
{{#let (concat (or item.LocalBindAddress '127.0.0.1') ':' item.LocalBindPort) as |combinedAddress| }}
|
||||
<li class="port">
|
||||
<CopyButtonFeedback
|
||||
@copy={{combinedAddress}}
|
||||
@name="Address"
|
||||
<CopyButton
|
||||
@value={{combinedAddress}}
|
||||
@name="Address"
|
||||
/>
|
||||
<span>{{combinedAddress}}</span>
|
||||
</li>
|
||||
|
@ -80,7 +80,7 @@
|
|||
<td class="combined-address">
|
||||
{{#if combinedAddress}}
|
||||
<span data-test-combined-address>{{combinedAddress}}</span>
|
||||
<CopyButtonFeedback @copy={{combinedAddress}} @name="Combined Address" />
|
||||
<CopyButton @copy={{combinedAddress}} @name="Combined Address" />
|
||||
{{else}}
|
||||
{{'-'}}
|
||||
{{/if}}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | copy button feedback', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function(assert) {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
// Handle any actions with this.on('myAction', function(val) { ... });
|
||||
|
||||
await render(hbs`{{copy-button-feedback value='Click Me'}}`);
|
||||
|
||||
assert.dom('*').hasText('Click Me');
|
||||
|
||||
// Template block usage:
|
||||
await render(hbs`
|
||||
{{#copy-button-feedback}}Click Me{{/copy-button-feedback}}
|
||||
`);
|
||||
|
||||
assert.dom('*').hasText('Click Me');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue