mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
add copy button to kv secrets masked input (#5627)
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
.masked-input {
|
.masked-input {
|
||||||
position: relative;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.masked-input .masked-value {
|
.masked-input.masked.display-only,
|
||||||
padding-left: 2.5rem;
|
.masked-input:not(.masked) {
|
||||||
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to style the boxes the same everywhere so they
|
// we want to style the boxes the same everywhere so they
|
||||||
@@ -11,14 +13,17 @@
|
|||||||
.masked-input.masked .masked-value {
|
.masked-input.masked .masked-value {
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
font-family: $family-primary;
|
font-family: $family-primary;
|
||||||
}
|
|
||||||
|
|
||||||
.masked-input.masked .masked-value {
|
|
||||||
line-height: 2.5;
|
line-height: 2.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.masked-input.display-only .masked-value {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
|
||||||
// aligns the boxes on the input page
|
// aligns the boxes on the input page
|
||||||
.masked-input.masked:not(.display-only) .masked-value {
|
.masked-input.masked:not(.display-only) .masked-value {
|
||||||
line-height: 3;
|
line-height: 3;
|
||||||
|
border-radius: $radius 0 0 $radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
//override bulma's pre styling
|
//override bulma's pre styling
|
||||||
@@ -27,48 +32,52 @@
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
padding-left: $spacing-s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.masked-input-toggle {
|
.button.masked-input-toggle,
|
||||||
background: transparent;
|
.button.copy-button {
|
||||||
position: absolute;
|
min-width: $spacing-xl;
|
||||||
height: auto;
|
border-left: 0;
|
||||||
top: $size-6/4;
|
border-radius: 0 $radius $radius 0;
|
||||||
bottom: $size-6/4;
|
color: $grey;
|
||||||
left: 1px;
|
}
|
||||||
line-height: 1rem;
|
|
||||||
min-width: 0;
|
|
||||||
max-height: 2rem;
|
|
||||||
padding: 0 $size-8;
|
|
||||||
z-index: 100;
|
|
||||||
border: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
color: $blue;
|
|
||||||
|
|
||||||
&:active,
|
.display-only {
|
||||||
&.is-active,
|
.button.masked-input-toggle,
|
||||||
&:focus,
|
.button.copy-button {
|
||||||
&.is-focused,
|
background: transparent;
|
||||||
&:hover,
|
height: auto;
|
||||||
&:focus:not(:active) {
|
line-height: 1rem;
|
||||||
color: $blue;
|
min-width: $spacing-l;
|
||||||
|
z-index: 100;
|
||||||
border: 0;
|
border: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
color: $grey-light;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&.is-active,
|
||||||
|
&:focus,
|
||||||
|
&.is-focused,
|
||||||
|
&:hover,
|
||||||
|
&:focus:not(:active) {
|
||||||
|
color: $blue;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.masked-input.display-only .masked-input-toggle {
|
.masked-input.masked .masked-value {
|
||||||
top: 0;
|
color: $grey-light;
|
||||||
font-size: 0.5rem;
|
}
|
||||||
height: 1rem;
|
|
||||||
padding-left: 0;
|
.masked-input:not(.masked) .masked-input-toggle {
|
||||||
|
color: $blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.masked-input .input:focus + .masked-input-toggle {
|
.masked-input .input:focus + .masked-input-toggle {
|
||||||
background: rgba($white, 0.95);
|
background: rgba($white, 0.95);
|
||||||
}
|
}
|
||||||
|
|
||||||
.masked-input.masked .masked-value,
|
|
||||||
.masked-input.masked .masked-input-toggle {
|
|
||||||
color: $grey-light;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="masked-input {{if shouldObscure "masked"}} {{if displayOnly "display-only"}}" data-test-masked-input>
|
<div class="masked-input {{if shouldObscure "masked"}} {{if displayOnly "display-only"}} {{if allowCopy "allow-copy"}}" data-test-masked-input>
|
||||||
{{#if displayOnly}}
|
{{#if displayOnly}}
|
||||||
<pre class="masked-value display-only is-word-break">{{displayValue}}</pre>
|
<pre class="masked-value display-only is-word-break">{{displayValue}}</pre>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -15,7 +15,16 @@
|
|||||||
data-test-textarea
|
data-test-textarea
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<button {{action "toggleMask"}} class="{{if (eq value "") "has-text-grey"}} masked-input-toggle button is-compact" data-test-button>
|
{{#if allowCopy}}
|
||||||
|
<CopyButton
|
||||||
|
@clipboardText={{value}}
|
||||||
|
@class="copy-button button is-compact"
|
||||||
|
data-test-copy-button
|
||||||
|
>
|
||||||
|
<ICon @glyph="copy" aria-hidden="true" @size=16 />
|
||||||
|
</CopyButton>
|
||||||
|
{{/if}}
|
||||||
|
<button {{action "toggleMask"}} class="{{if (eq value "") "has-text-grey"}} masked-input-toggle button {{if displayOnly "is-compact"}}" data-test-button>
|
||||||
{{i-con glyph=(if shouldObscure "hidden" "visible") aria-hidden="true" size=16}}
|
{{i-con glyph=(if shouldObscure "hidden" "visible") aria-hidden="true" size=16}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
@onChange={{@editActions.handleChange}}
|
@onChange={{@editActions.handleChange}}
|
||||||
@value={{secret.value}}
|
@value={{secret.value}}
|
||||||
data-test-secret-value="true"
|
data-test-secret-value="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="column is-narrow info-table-row-edit">
|
<div class="column is-narrow info-table-row-edit">
|
||||||
{{#if (eq @secretData.length (inc index))}}
|
{{#if (eq @secretData.length (inc index))}}
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
{{action @editActions.deleteRow secret.name}}
|
{{action @editActions.deleteRow secret.name}}
|
||||||
aria-label="Delete row"
|
aria-label="Delete row"
|
||||||
>
|
>
|
||||||
<ICon
|
<ICon
|
||||||
@size="22"
|
@size="22"
|
||||||
@glyph="trash-a"
|
@glyph="trash-a"
|
||||||
@excludeIconClass={{true}}
|
@excludeIconClass={{true}}
|
||||||
@@ -78,4 +78,4 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{#each-in modelForData.secretData as |key value|}}
|
{{#each-in modelForData.secretData as |key value|}}
|
||||||
{{#info-table-row label=key value=value alwaysRender=true}}
|
{{#info-table-row label=key value=value alwaysRender=true}}
|
||||||
{{masked-input value=value displayOnly=true}}
|
{{masked-input value=value displayOnly=true allowCopy=true}}
|
||||||
{{/info-table-row}}
|
{{/info-table-row}}
|
||||||
{{/each-in}}
|
{{/each-in}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -40,6 +40,18 @@ module('Integration | Component | masked input', function(hooks) {
|
|||||||
assert.notOk(component.textareaIsPresent);
|
assert.notOk(component.textareaIsPresent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it renders a copy button when allowCopy is true', async function(assert) {
|
||||||
|
await render(hbs`{{masked-input allowCopy=true}}`);
|
||||||
|
|
||||||
|
assert.ok(component.copyButtonIsPresent);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it does not render a copy button when allowCopy is false', async function(assert) {
|
||||||
|
await render(hbs`{{masked-input allowCopy=false}}`);
|
||||||
|
|
||||||
|
assert.notOk(component.copyButtonIsPresent);
|
||||||
|
});
|
||||||
|
|
||||||
test('it unmasks text on focus', async function(assert) {
|
test('it unmasks text on focus', async function(assert) {
|
||||||
this.set('value', 'value');
|
this.set('value', 'value');
|
||||||
await render(hbs`{{masked-input value=value}}`);
|
await render(hbs`{{masked-input value=value}}`);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export default {
|
|||||||
wrapperClass: attribute('class', '[data-test-masked-input]'),
|
wrapperClass: attribute('class', '[data-test-masked-input]'),
|
||||||
enterText: fillable('[data-test-textarea]'),
|
enterText: fillable('[data-test-textarea]'),
|
||||||
textareaIsPresent: isPresent('[data-test-textarea]'),
|
textareaIsPresent: isPresent('[data-test-textarea]'),
|
||||||
|
copyButtonIsPresent: isPresent('[data-test-copy-button]'),
|
||||||
toggleMasked: clickable('[data-test-button]'),
|
toggleMasked: clickable('[data-test-button]'),
|
||||||
async focusField() {
|
async focusField() {
|
||||||
return focus('[data-test-textarea]');
|
return focus('[data-test-textarea]');
|
||||||
|
|||||||
Reference in New Issue
Block a user