UI: HDS adoption replace <CopyButton> component (#22333)

* Part 1: Upgrade HDS to 2.9.0 (#22311)

* UI: HDS adoption replace <CopyButton> part 2 (#22356)

* certificate-card.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* scope-form.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* fix tests caused by changing certificate-card. change hds copy button in certificate-card.hbs

* json-editor.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* masked-input.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* fix error with certificate-card.hbs copy button

* fix tests that deal with certificate-card.hbs

* add class to hds copy buttons to maintain similar styling to curent UI

* info-table-row.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* undo change that should instead by merged in from main

* change tooltip copy button to white. cleanup

* add extra tet for oidc scope form. edit css class for the white icon copy button

* fix tests

* UI: HDS adoption replace <CopyButton> part 3 (#22614)

* encrypt.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* decrypt.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* datakey.hbs. replace 6 <CopyButton> with <Hds::Copy::Button>

* rewrap.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* hmac.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* fix typo

* add copy-close class to copy & close buttons

* export.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>. fix styling

* sign.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* fix test caused by changing <pre> tag to <code> in export.hbs

* rename class

* add extra style to class needed for part 4 of copy button replacement

* UI: HDS adoption replace <CopyButton> part 4 (#22749)

* user-menu.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* transit-form-show.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* configure-ssh-secret.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* tool-hash.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* tool-random.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* tool-rewrap.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* tool-unwrap.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* tool-wrap.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* paths.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* code-snippet.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* cleanup css for code-snippet. add comments for getting rid of code-snippet and replacing with <Hds::Copy::Snippet

* change code-snippet copy icon to gray to match original design

* change code-snippet class

* accounts.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* hover-copy-button.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* add.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* show.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* copy-secret-dropdown.hbs: replace 1 <CopyButton> with <Hds::Copy::Button>

* change styling of 'link' copy buttons

* generate-credentials.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* transform-show-transformation.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* sign.hbs: replace 2 <CopyButton> with <Hds::Copy::Button>

* hide some copy buttons' icons and use original flash message

* undo cleanup of scss file so that I can put cleanup all into one PR to be more organized

* update code snippet copy button

* UI: HDS adoption replace <CopyButton> part 5: Cleanup (#22884)

* remove unecessary code-snippet.scssn class

* remove copy classes from masked-input.scss

* remove copy button class from text-file.scss

* uninstall ember-cli-clipboard 0.16.0 since there is no longer structure <CopyButton>

* remove copyright message from code-snippet.scss to avoid merge conflicts with main, where the file is deleted

* replace 2 classes with one

* remove unecessary class from copy button

* cleanup classes

* revert changes to avoid merge conflicts

* remove is-block class

* conditionally render private key

* add more info to comment

* remove HoverCopyButton

* add missing selector

* fix control group padding

---------

Co-authored-by: clairebontempo@gmail.com <clairebontempo@gmail.com>
Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>

* rename class to transparent background

* remove unused test selectors

* replace transit actions with Copy::Snippet

* replace transfrom code blocks with code snippet component

* revert extra css fiddling

* misc cleanup, unused action

* remove copy & close buttons from transit modals

* remove is- from class naming

* remove hds-copy-button class

* add other grey class

* more small cleanup

* add -top to margin

* add changelog

---------

Co-authored-by: clairebontempo@gmail.com <clairebontempo@gmail.com>
Co-authored-by: claire bontempo <68122737+hellobontempo@users.noreply.github.com>
This commit is contained in:
malinac02 2023-09-15 16:46:10 -07:00 committed by GitHub
parent d939a20310
commit 79b2f09715
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 513 additions and 917 deletions

3
changelog/22333.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:improvement
ui: Implement Helios Design System copy button component making copy buttons accessible
```

View file

@ -1,29 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
/**
* @module HoverCopyButton
* The `HoverCopyButton` is used on dark backgrounds to show a copy button.
*
* @example ```js
* <HoverCopyButton @copyValue={{stringify this.model.id}} @alwaysShow={{true}} />```
*
* @param {string} copyValue - The value to be copied.
* @param {boolean} [alwaysShow] - Boolean that affects the class.
*/
export default class HoverCopyButton extends Component {
get alwaysShow() {
return this.args.alwaysShow || false;
}
get copyValue() {
return this.args.copyValue || false;
}
@tracked tooltipText = 'Copy';
}

View file

@ -47,11 +47,6 @@ export default class KeymgmtKeyEdit extends Component {
return this.args.mode === 'create'; return this.args.mode === 'create';
} }
@action
toggleModal(bool) {
this.isDeleteModalOpen = bool;
}
@task @task
@waitFor @waitFor
*saveKey(evt) { *saveKey(evt) {

View file

@ -40,14 +40,13 @@
</li> </li>
{{/if}} {{/if}}
<li class="action"> <li class="action">
<CopyButton <Hds::Copy::Button
@clipboardText={{this.auth.currentToken}} @text="Copy token"
class="link" @textToCopy={{this.auth.currentToken}}
@buttonType="button" @isFullWidth={{true}}
@success={{action (set-flash-message "Token copied!")}} class="in-dropdown link is-flex-start"
> {{on "click" (fn (set-flash-message "Token copied!"))}}
Copy token />
</CopyButton>
</li> </li>
{{#if (is-before (now interval=1000) this.auth.tokenExpirationDate)}} {{#if (is-before (now interval=1000) this.auth.tokenExpirationDate)}}
{{#if this.auth.authData.renewable}} {{#if this.auth.authData.renewable}}

View file

@ -214,13 +214,6 @@ export default Component.extend(TRANSIT_PARAMS, {
arr.forEach((param) => this.set(param, null)); arr.forEach((param) => this.set(param, null));
}, },
toggleModal(successMessage) {
if (!!successMessage && typeof successMessage === 'string') {
this.flashMessages.success(successMessage);
}
this.toggleProperty('isModalActive');
},
doSubmit(data, options = {}, maybeEvent) { doSubmit(data, options = {}, maybeEvent) {
const event = options.type === 'submit' ? options : maybeEvent; const event = options.type === 'submit' ? options : maybeEvent;
if (event) { if (event) {

View file

@ -66,13 +66,6 @@ $console-close-height: 35px;
} }
} }
.console-ui-panel-content.hover-copy-button,
.console-ui-panel-content.hover-copy-button-static {
top: auto;
bottom: 0;
right: 0;
}
.console-ui-input { .console-ui-input {
align-items: center; align-items: center;
display: flex; display: flex;

View file

@ -34,20 +34,3 @@
.control-group .authorizations { .control-group .authorizations {
margin-top: $size-9; margin-top: $size-9;
} }
.control-group .hover-copy-button-static {
color: $orange;
}
.control-group-token-text {
color: $grey;
position: relative;
padding: $size-8 0;
.hover-copy-button-static {
position: relative;
top: auto;
left: auto;
display: inline-block;
}
}

View file

@ -1,30 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
.has-copy-button {
position: relative;
color: $grey;
}
.hover-copy-button,
.hover-copy-button-static {
position: absolute;
top: 0.5rem;
right: 0.5rem;
}
.hover-copy-button {
opacity: 0;
pointer-events: none;
transition: opacity $speed ease-in-out;
will-change: opacity;
z-index: 10;
}
.has-copy-button:hover .hover-copy-button,
.has-copy-button:focus .hover-copy-button,
.hover-copy-button .copy-button:focus {
opacity: 1;
pointer-events: auto;
}

View file

@ -49,7 +49,6 @@
} }
.button.masked-input-toggle, .button.masked-input-toggle,
.button.copy-button,
.button.download-button { .button.download-button {
min-width: $spacing-xl; min-width: $spacing-xl;
border-left: 0; border-left: 0;
@ -57,7 +56,6 @@
box-shadow: 0 3px 1px 0px rgba(10, 10, 10, 0.12); box-shadow: 0 3px 1px 0px rgba(10, 10, 10, 0.12);
} }
.button.copy-button,
.button.download-button { .button.download-button {
border-radius: 0; border-radius: 0;
} }
@ -68,7 +66,6 @@
.display-only { .display-only {
.button.masked-input-toggle, .button.masked-input-toggle,
.button.copy-button,
.button.download-button { .button.download-button {
background: transparent; background: transparent;
height: auto; height: auto;

View file

@ -12,8 +12,7 @@
line-height: inherit; line-height: inherit;
} }
} }
.button.masked-input-toggle, .button.masked-input-toggle {
.button.copy-button {
display: flex; display: flex;
} }
} }

View file

@ -70,7 +70,6 @@
@import './components/features-selection'; @import './components/features-selection';
@import './components/form-section'; @import './components/form-section';
@import './components/global-flash'; @import './components/global-flash';
@import './components/hover-copy-button';
@import './components/icon'; @import './components/icon';
@import './components/init-illustration'; @import './components/init-illustration';
@import './components/info-table-row'; @import './components/info-table-row';

View file

@ -14,10 +14,9 @@
display: inline-block; display: inline-block;
font-size: $size-8; font-size: $size-8;
font-weight: $font-weight-semibold; font-weight: $font-weight-semibold;
height: 2.5rem; min-height: 2.25rem;
line-height: 1.6;
min-width: 6rem; min-width: 6rem;
padding: $size-10 $size-8; padding: 0.5625rem 0.9375rem;
position: relative; position: relative;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
@ -332,3 +331,58 @@ a.button.disabled {
cursor: not-allowed; cursor: not-allowed;
} }
} }
// Existing class on <Hds::Copy::Button> component, modifying to match existing UI Structure buttons
.hds-copy-button {
font-weight: $font-weight-semibold;
box-shadow: $box-shadow-low;
border-radius: $radius;
&.white-icon svg {
color: $white;
}
&.icon-grey-300 svg {
color: $ui-gray-300;
}
&.icon-grey-500 svg {
color: $ui-gray-500;
}
&.icon-only {
margin-right: $spacing-xxs;
margin-left: $spacing-xxs;
}
&.transparent {
background: none;
border: none;
box-shadow: none;
}
&.primary {
background-color: $blue;
border-color: darken($blue, 2%);
color: $white;
font-weight: $font-weight-bold;
text-shadow: 0 1px 1px rgba($black, 0.25);
svg {
color: $white;
}
}
&.secondary {
background-color: $grey-lightest;
border: 1px solid $grey-light;
}
&.in-dropdown {
div {
font-size: $size-7;
}
svg {
color: transparent;
}
}
}

View file

@ -23,6 +23,13 @@
} }
// position // position
.top-right-absolute {
position: absolute;
top: 0.5rem;
right: 0.5rem;
z-index: 10;
}
.is-in-bottom-right { .is-in-bottom-right {
position: absolute; position: absolute;
bottom: 1rem; bottom: 1rem;

View file

@ -107,10 +107,6 @@
margin-top: -$spacing-xxl; margin-top: -$spacing-xxl;
} }
.has-top-margin-xxs {
margin: $spacing-xxs 0;
}
.has-right-margin-xxs { .has-right-margin-xxs {
margin-right: $spacing-xxs; margin-right: $spacing-xxs;
} }
@ -147,6 +143,10 @@
margin-bottom: $spacing-xxl; margin-bottom: $spacing-xxl;
} }
.has-top-margin-xxs {
margin-top: $spacing-xxs;
}
.has-top-margin-s { .has-top-margin-s {
margin-top: $spacing-s; margin-top: $spacing-s;
} }

View file

@ -23,14 +23,7 @@
</div> </div>
<div class="field is-grouped-split box is-fullwidth is-bottomless"> <div class="field is-grouped-split box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy" @textToCopy={{@model.publicKey}} class="primary" />
@clipboardText={{@model.publicKey}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Public Key copied!")}}
>
Copy
</CopyButton>
</div> </div>
<div class="control"> <div class="control">
<ConfirmAction <ConfirmAction

View file

@ -3,7 +3,7 @@
SPDX-License-Identifier: BUSL-1.1 SPDX-License-Identifier: BUSL-1.1
~}} ~}}
<div class="console-ui-output has-copy-button"> <div class="console-ui-output has-text-grey">
<JsonEditor <JsonEditor
@showToolbar={{false}} @showToolbar={{false}}
@value={{stringify this.content}} @value={{stringify this.content}}
@ -12,5 +12,10 @@
@gutters={{false}} @gutters={{false}}
@theme="hashi auto-height" @theme="hashi auto-height"
/> />
<HoverCopyButton @copyValue={{stringify this.content}} /> <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{stringify this.content}}
class="transparent icon-grey-500 top-right-absolute"
/>
</div> </div>

View file

@ -3,7 +3,7 @@
SPDX-License-Identifier: BUSL-1.1 SPDX-License-Identifier: BUSL-1.1
~}} ~}}
<div class="console-ui-output has-copy-button"> <div class="console-ui-output has-text-grey">
<pre> <pre>
Keys Keys
{{#each this.list as |item|}} {{#each this.list as |item|}}
@ -11,5 +11,10 @@
{{/each}} {{/each}}
</pre> </pre>
<HoverCopyButton @copyValue={{multi-line-join this.list}} /> <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{multi-line-join this.list}}
class="transparent icon-grey-500 top-right-absolute"
/>
</div> </div>

View file

@ -3,7 +3,12 @@
SPDX-License-Identifier: BUSL-1.1 SPDX-License-Identifier: BUSL-1.1
~}} ~}}
<div class="console-ui-output has-copy-button"> <div class="console-ui-output has-text-grey">
<pre>{{this.columns}}</pre> <pre>{{this.columns}}</pre>
<HoverCopyButton @copyValue={{this.columns}} /> <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{this.columns}}
class="transparent icon-grey-500 top-right-absolute"
/>
</div> </div>

View file

@ -3,7 +3,12 @@
SPDX-License-Identifier: BUSL-1.1 SPDX-License-Identifier: BUSL-1.1
~}} ~}}
<div class="console-ui-output has-copy-button"> <div class="console-ui-output has-text-grey">
<pre>{{@content}}</pre> <pre>{{@content}}</pre>
<HoverCopyButton @copyValue={{this.content}} @alwaysShow={{true}} /> <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{@content}}
class="transparent icon-grey-500 top-right-absolute"
/>
</div> </div>

View file

@ -16,8 +16,8 @@
</div> </div>
{{else}} {{else}}
{{#if this.unwrapData}} {{#if this.unwrapData}}
<div class="control-group-success {{if this.unwrapData 'is-editor'}}"> <div class="control-group-success is-editor">
<div class="has-copy-button"> <div class="is-relative">
<JsonEditor <JsonEditor
data-test-json-viewer data-test-json-viewer
@showToolbar={{false}} @showToolbar={{false}}
@ -27,7 +27,12 @@
@gutters={{false}} @gutters={{false}}
@theme="hashi-read-only auto-height" @theme="hashi-read-only auto-height"
/> />
<HoverCopyButton @copyValue={{stringify this.unwrapData}} /> <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{stringify this.unwrapData}}
class="transparent top-right-absolute"
/>
</div> </div>
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">

View file

@ -48,8 +48,13 @@
</div> </div>
{{#if (or (not this.model.requestEntity) this.currentUserIsRequesting)}} {{#if (or (not this.model.requestEntity) this.currentUserIsRequesting)}}
<div class="message is-list is-highlight has-copy-button" tabindex="-1" data-test-accessor-callout> <div class="message is-highlight" data-test-accessor-callout>
<HoverCopyButton @alwaysShow={{true}} @copyValue={{this.model.id}} /> <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{this.model.id}}
class="transparent top-right-absolute"
/>
<div class="message-body"> <div class="message-body">
<h4 class="title is-7 is-marginless"> <h4 class="title is-7 is-marginless">
Accessor Accessor
@ -85,11 +90,14 @@
{{/if}} {{/if}}
{{#if this.controlGroupResponse.token}} {{#if this.controlGroupResponse.token}}
<p class="control-group-token-text" data-test-token> <div class="is-flex-row has-bottom-margin-m has-top-margin-m" data-test-token>
Weve saved your request token, but you may want to copy it just in case: <p class="has-text-grey has-padding-xxs">
<span class="tag has-font-monospaced" data-test-token-value>{{this.controlGroupResponse.token}}</span> Weve saved your request token, but you may want to copy it just in case:
<HoverCopyButton @alwaysShow={{true}} @copyValue={{this.controlGroupResponse.token}} /> </p>
</p> <div>
<Hds::Copy::Snippet data-test-token-value @textToCopy={{this.controlGroupResponse.token}} @color="secondary" />
</div>
</div>
{{/if}} {{/if}}
{{! template-lint-configure simple-unless "warn" }} {{! template-lint-configure simple-unless "warn" }}
{{#unless (and this.model.approved (or (not this.model.requestEntity) this.currentUserIsRequesting))}} {{#unless (and this.model.approved (or (not this.model.requestEntity) this.currentUserIsRequesting))}}

View file

@ -92,25 +92,11 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy credentials" @textToCopy={{this.model.toCreds}} class="primary" />
@clipboardText={{this.model.toCreds}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Credentials copied!")}}
>
Copy credentials
</CopyButton>
</div> </div>
{{#if this.model.leaseId}} {{#if this.model.leaseId}}
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy Lease ID" @textToCopy={{this.model.leaseId}} class="secondary" />
@clipboardText={{this.model.leaseId}}
@class="button"
@buttonType="button"
@success={{action (set-flash-message "Lease ID copied!")}}
>
Copy Lease ID
</CopyButton>
</div> </div>
{{/if}} {{/if}}
<div class="control"> <div class="control">

View file

@ -1,24 +0,0 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
~}}
<div class={{if this.alwaysShow "hover-copy-button-static" "hover-copy-button"}} data-test-hover-copy>
<ToolTip @onClose={{action (mut this.tooltipText) "Copy"}} as |T|>
<T.Trigger data-test-tooltip-trigger tabindex="-1">
<CopyButton
data-test-hover-copy-button
class="copy-button button is-compact is-transparent"
@clipboardText={{this.copyValue}}
@success={{action (mut this.tooltipText) "Copied!"}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</T.Trigger>
<T.Content @defaultClass="tool-tip">
<div class="box" data-test-hover-copy-tooltip-text>
{{this.tooltipText}}
</div>
</T.Content>
</ToolTip>
</div>

View file

@ -86,17 +86,16 @@
> >
<section class="modal-card-body"> <section class="modal-card-body">
<div class="is-flex-between is-flex-center has-bottom-margin-s"> <div class="is-flex-between is-flex-center has-bottom-margin-s">
<p data-test-modal-copy> <p data-test-modal-text>
Example of a JSON template for scopes: Example of a JSON template for scopes:
</p> </p>
<CopyButton <Hds::Copy::Button
class="button is-transparent" @text="Copy"
@clipboardText={{this.exampleTemplate}} @isIconOnly={{true}}
@buttonType="button" @textToCopy={{this.exampleTemplate}}
@success={{fn (set-flash-message "Example template copied!")}} class="transparent"
> data-test-copy-button
<Icon @name="clipboard-copy" aria-label="Copy" /> />
</CopyButton>
</div> </div>
{{! code-mirror modifier does not render value initially in wormhole until focus event fires }} {{! code-mirror modifier does not render value initially in wormhole until focus event fires }}
{{! wait until the Modal is rendered and then show the JsonEditor }} {{! wait until the Modal is rendered and then show the JsonEditor }}

View file

@ -22,14 +22,7 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy" @textToCopy={{@sum}} class="primary" />
@clipboardText={{@sum}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Hashed data copied!")}}
>
Copy
</CopyButton>
</div> </div>
<div class="control"> <div class="control">
<button {{on "click" this.onClear}} type="button" class="button" data-test-tools-back={{true}}> <button {{on "click" this.onClear}} type="button" class="button" data-test-tools-back={{true}}>

View file

@ -18,14 +18,7 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy" @textToCopy={{@random_bytes}} class="primary" />
@clipboardText={{@random_bytes}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Random bytes copied!")}}
>
Copy
</CopyButton>
</div> </div>
<div class="control"> <div class="control">
<button {{on "click" this.onClear}} type="button" class="button"> <button {{on "click" this.onClear}} type="button" class="button">

View file

@ -29,14 +29,7 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy" @textToCopy={{@rewrap_token}} class="primary" />
@clipboardText={{@rewrap_token}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Token copied!")}}
>
Copy
</CopyButton>
</div> </div>
<div class="control"> <div class="control">
<button {{on "click" this.onClear}} type="button" class="button"> <button {{on "click" this.onClear}} type="button" class="button">

View file

@ -65,14 +65,7 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy" @textToCopy={{stringify @unwrap_data}} class="primary" />
@clipboardText={{stringify @unwrap_data}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Data copied!")}}
>
Copy
</CopyButton>
</div> </div>
<div class="control"> <div class="control">
<button {{on "click" this.onClear}} type="button" class="button"> <button {{on "click" this.onClear}} type="button" class="button">

View file

@ -29,14 +29,7 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy" @textToCopy={{@token}} class="primary" />
@clipboardText={{@token}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Token copied!")}}
>
Copy
</CopyButton>
</div> </div>
<div class="control"> <div class="control">
<button {{on "click" this.onClear}} type="button" class="button"> <button {{on "click" this.onClear}} type="button" class="button">

View file

@ -42,15 +42,7 @@
</div> </div>
<div class="copy-text level"> <div class="copy-text level">
{{#let (concat "vault write " this.model.backend "/encode/" this.cliCommand) as |copyEncodeCommand|}} {{#let (concat "vault write " this.model.backend "/encode/" this.cliCommand) as |copyEncodeCommand|}}
<code>vault write {{this.model.backend}}/encode/{{this.cliCommand}}</code> <CodeSnippet @codeBlock={{copyEncodeCommand}} @isIconOnly={{true}} />
<CopyButton
class="button is-transparent level-right"
@clipboardText={{copyEncodeCommand}}
@buttonType="button"
@success={{action (set-flash-message "Command copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
{{/let}} {{/let}}
</div> </div>
</div> </div>
@ -64,15 +56,7 @@
</div> </div>
<div class="copy-text level"> <div class="copy-text level">
{{#let (concat "vault write " this.model.backend "/decode/" this.cliCommand) as |copyDecodeCommand|}} {{#let (concat "vault write " this.model.backend "/decode/" this.cliCommand) as |copyDecodeCommand|}}
<code>vault write {{this.model.backend}}/decode/{{this.cliCommand}}</code> <CodeSnippet @codeBlock={{copyDecodeCommand}} @isIconOnly={{true}} />
<CopyButton
class="button is-transparent level-right"
@clipboardText={{copyDecodeCommand}}
@buttonType="button"
@success={{action (set-flash-message "Command copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
{{/let}} {{/let}}
</div> </div>
</div> </div>

View file

@ -155,14 +155,13 @@
<nav class="menu" aria-label="copy public key"> <nav class="menu" aria-label="copy public key">
<ul class="menu-list"> <ul class="menu-list">
<li class="action"> <li class="action">
<CopyButton <Hds::Copy::Button
@clipboardText={{meta.public_key}} @text="Copy Public Key"
@class="link button is-transparent" @textToCopy={{meta.public_key}}
@buttonType="button" @isFullWidth={{true}}
@success={{action (set-flash-message "Public key copied!")}} class="in-dropdown link is-flex-start"
> {{on "click" (action (set-flash-message "Public key copied!"))}}
Copy Public Key />
</CopyButton>
</li> </li>
</ul> </ul>
</nav> </nav>

View file

@ -78,76 +78,15 @@
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
{{#if (eq @param "plaintext")}} {{#if (eq @param "plaintext")}}
<h2 class="title is-6">Plaintext</h2> <h2 class="has-text-weight-semibold is-6">Plaintext</h2>
<div class="copy-text level"> <p class="sub-text">Plaintext is base64 encoded</p>
<code class="level-left">{{@plaintext}}</code> <Hds::Copy::Snippet class="has-bottom-margin-m" @textToCopy={{@plaintext}} @color="secondary" />
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@plaintext}}
@buttonType="button"
@success={{action (set-flash-message "Plaintext copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
<p class="help has-bottom-margin-m">Plaintext is base64 encoded</p>
<h2 class="title is-6">Ciphertext</h2>
<div class="copy-text level">
<code class="level-left">{{@ciphertext}}</code>
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action (set-flash-message "Ciphertext copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
<CopyButton
class="button is-primary"
data-test-button="modal-copy-close"
@clipboardText={{@plaintext}}
@buttonType="button"
@success={{action (set-flash-message "Plaintext copied!")}}
>
Copy Plaintext
</CopyButton>
<CopyButton
class="button is-primary"
data-test-button="modal-copy-close"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action (set-flash-message "Ciphertext copied!")}}
>
Copy Ciphertext
</CopyButton>
<button type="submit" class="button is-secondary" onclick={{action (mut @isModalActive) false}}>Close</button>
{{else}}
<h2 class="title is-6">Ciphertext</h2>
<div class="copy-text level">
<code class="level-left">{{@ciphertext}}</code>
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action (set-flash-message "Ciphertext copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
<CopyButton
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action @toggleModal "Ciphertext copied!"}}
>
Copy &amp; Close
</CopyButton>
{{/if}} {{/if}}
<h2 class="has-text-weight-semibold is-6">Ciphertext</h2>
<Hds::Copy::Snippet @textToCopy={{@ciphertext}} @color="secondary" />
</div> </div>
</section> </section>
<footer class="modal-card-foot">
<button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
</footer>
</Modal> </Modal>

View file

@ -59,32 +59,13 @@
<Modal @title="Copy your unwrapped data" @onClose={{action (mut @isModalActive) false}} @isActive={{@isModalActive}}> <Modal @title="Copy your unwrapped data" @onClose={{action (mut @isModalActive) false}} @isActive={{@isModalActive}}>
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<h2 class="title is-6">Plaintext</h2> <h2 class="has-text-weight-semibold is-6">Plaintext</h2>
<div class="copy-text level"> <p class="sub-text">Plaintext is base64 encoded</p>
<code class="level-left" data-test-encrypted-value="plaintext">{{@plaintext}}</code> <Hds::Copy::Snippet @textToCopy={{@plaintext}} @color="secondary" data-test-encrypted-value="plaintext" />
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@plaintext}}
@buttonType="button"
@success={{action (set-flash-message "Plaintext copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
<p class="help">Plaintext is base64 encoded</p>
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{@plaintext}}
@buttonType="button"
@success={{action @toggleModal "Plaintext copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>
{{/if}} {{/if}}

View file

@ -78,29 +78,10 @@
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<h2 class="title is-6">Ciphertext</h2> <h2 class="title is-6">Ciphertext</h2>
<div class="copy-text level"> <Hds::Copy::Snippet @textToCopy={{@ciphertext}} @color="secondary" data-test-encrypted-value="ciphertext" />
<code class="level-left" data-test-encrypted-value="ciphertext">{{@ciphertext}}</code>
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action (set-flash-message "Ciphertext copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action @toggleModal "Ciphertext copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>

View file

@ -69,29 +69,29 @@
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<h2 class="title is-6">Wrapped Key</h2> <h2 class="title is-6">Wrapped Key</h2>
<div class="copy-text level"> {{#if this.wrapTTL}}
<pre data-test-encrypted-value="export" class="level-left">{{if this.wrapTTL @wrappedToken (stringify @keys)}}</pre> <Hds::Copy::Snippet
<CopyButton class="has-bottom-margin-m"
class="button is-compact is-transparent level-right" @textToCopy={{@wrappedToken}}
data-test-button="modal-copy" @color="secondary"
@clipboardText={{if this.wrapTTL @wrappedToken (stringify @keys)}} data-test-encrypted-value="export"
@buttonType="button" />
@success={{action (set-flash-message "Token copied!")}} {{else}}
> <div class="copy-text level is-relative">
<Icon @name="clipboard-copy" aria-label="Copy" /> <pre data-test-encrypted-value="export" class="level-left">
</CopyButton> {{stringify @keys}}
</div> </pre>
<Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{stringify @keys}}
class="transparent top-right-absolute"
/>
</div>
{{/if}}
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{if this.wrapTTL @wrappedToken (stringify @keys)}}
@buttonType="button"
@success={{action @toggleModal "Token copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>

View file

@ -55,29 +55,10 @@
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<h2 class="title is-6">HMAC</h2> <h2 class="title is-6">HMAC</h2>
<div class="copy-text level"> <Hds::Copy::Snippet @textToCopy={{@hmac}} @color="secondary" data-test-encrypted-value="hmac" />
<code class="level-left" data-test-encrypted-value="hmac">{{@hmac}}</code>
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@hmac}}
@buttonType="button"
@success={{action (set-flash-message "HMAC copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{@hmac}}
@buttonType="button"
@success={{action @toggleModal "HMAC copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>

View file

@ -67,29 +67,10 @@
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<h2 class="title is-6">Ciphertext</h2> <h2 class="title is-6">Ciphertext</h2>
<div class="copy-text level"> <Hds::Copy::Snippet @textToCopy={{@ciphertext}} @color="secondary" />
<code class="level-left" data-test-encrypted-value="ciphertext">{{@ciphertext}}</code>
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action (set-flash-message "Ciphertext copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{@ciphertext}}
@buttonType="button"
@success={{action @toggleModal "Ciphertext copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>

View file

@ -129,29 +129,10 @@
<section class="modal-card-body"> <section class="modal-card-body">
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<h2 class="title is-6">Signature</h2> <h2 class="title is-6">Signature</h2>
<div class="copy-text level"> <Hds::Copy::Snippet @textToCopy={{@signature}} @color="secondary" data-test-encrypted-value="signature" />
<code class="level-left" data-test-encrypted-value="signature">{{@signature}}</code>
<CopyButton
class="button is-compact is-transparent level-right"
data-test-button="modal-copy"
@clipboardText={{@signature}}
@buttonType="button"
@success={{action (set-flash-message "Signature copied!")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div>
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <button type="button" class="button is-primary" {{on "click" (fn (mut @isModalActive) false)}}>Close</button>
class="button is-primary copy-close"
data-test-button="modal-copy-close"
@clipboardText={{@signature}}
@buttonType="button"
@success={{action @toggleModal "Signature copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>

View file

@ -48,7 +48,6 @@
encodedBase64=this.encodedBase64 encodedBase64=this.encodedBase64
valid=this.valid valid=this.valid
doSubmit=(action "doSubmit") doSubmit=(action "doSubmit")
toggleModal=(action "toggleModal")
clearParams=(action "clearParams") clearParams=(action "clearParams")
}} }}
</div> </div>

View file

@ -37,7 +37,7 @@
{{#if this.model.signedKey}} {{#if this.model.signedKey}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless"> <div class="box is-fullwidth is-sideless is-paddingless is-marginless">
<Hds::Alert @type="inline" @color="warning" class="has-bottom-margin-s" as |A|> <Hds::Alert @type="inline" @color="warning" class="has-top-margin-s has-bottom-margin-s" as |A|>
<A.Title>Warning</A.Title> <A.Title>Warning</A.Title>
<A.Description> <A.Description>
You will not be able to access this information later, so please copy the information below. You will not be able to access this information later, so please copy the information below.
@ -59,25 +59,11 @@
</div> </div>
<div class="field is-grouped box is-fullwidth is-bottomless"> <div class="field is-grouped box is-fullwidth is-bottomless">
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy key" @textToCopy={{this.model.signedKey}} class="primary" />
@clipboardText={{this.model.signedKey}}
@class="button is-primary"
@buttonType="button"
@success={{action (set-flash-message "Key copied!")}}
>
Copy key
</CopyButton>
</div> </div>
{{#if this.model.leaseId}} {{#if this.model.leaseId}}
<div class="control"> <div class="control">
<CopyButton <Hds::Copy::Button @text="Copy lease ID" @textToCopy={{this.model.leaseId}} class="secondary" />
@clipboardText={{this.model.leaseId}}
@class="button"
@buttonType="button"
@success={{action (set-flash-message "Lease ID copied!")}}
>
Copy lease ID
</CopyButton>
</div> </div>
{{/if}} {{/if}}
<div class="control"> <div class="control">

View file

@ -20,15 +20,13 @@
{{@data}} {{@data}}
</code> </code>
</div> </div>
<div class="is-flex has-background-white-bis has-side-padding-s has-top-bottom-margin-negative-m"> <div class="is-flex-center has-background-white-bis has-side-padding-s has-top-bottom-margin-negative-m">
<CopyButton <Hds::Copy::Button
@text="Copy"
@isIconOnly={{true}}
@textToCopy={{@data}}
class="transparent is-paddingless"
data-test-copy-button data-test-copy-button
class="button is-transparent is-flex-v-centered" />
@clipboardText={{@data}}
@buttonType="button"
@success={{action (set-flash-message "Certificate copied")}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div> </div>
</Hds::Card::Container> </Hds::Card::Container>

View file

@ -22,10 +22,12 @@
<h4 class="field-title has-bottom-padding-m is-fullwidth"> <h4 class="field-title has-bottom-padding-m is-fullwidth">
{{concat "PGP Key " this.pgpKeyFile.filename}} {{concat "PGP Key " this.pgpKeyFile.filename}}
</h4> </h4>
<div class="message is-list has-copy-button" tabindex="-1"> <Hds::Copy::Snippet
<HoverCopyButton @copyValue={{this.pgpKey}} /> class="has-bottom-margin-s"
<code class="is-word-break" data-test-pgp-key-copy>{{this.pgpKey}}</code> @textToCopy={{this.pgpKey}}
</div> @color="secondary"
data-test-pgp-key-copy
/>
</div> </div>
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control"> <div class="control">

View file

@ -9,14 +9,10 @@
...attributes ...attributes
> >
<code class="has-text-white is-size-7">{{@codeBlock}}</code> <code class="has-text-white is-size-7">{{@codeBlock}}</code>
{{! replace with Hds::Copy::Button }} <Hds::Copy::Button
<CopyButton class="has-text-grey-light transparent icon-grey-300"
class="button is-compact is-transparent has-text-grey-light" @text="Copy"
@clipboardText={{or @clipboardCode @codeBlock}} @textToCopy={{or @clipboardCode @codeBlock}}
@buttonType="button" @isIconOnly={{@isIconOnly}}
@success={{action (set-flash-message "Code copied!")}} />
>
Copy
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
</div> </div>

View file

@ -8,14 +8,14 @@
<nav class="box menu"> <nav class="box menu">
<ul class="menu-list"> <ul class="menu-list">
<li class="action"> <li class="action">
<CopyButton <Hds::Copy::Button
@class="link" @text="Copy JSON"
@clipboardText={{@clipboardText}} @textToCopy={{@clipboardText}}
@success={{fn (set-flash-message "JSON Copied!")}} @isFullWidth={{true}}
class="in-dropdown link is-flex-start"
{{on "click" (action (set-flash-message "JSON Copied!"))}}
data-test-copy-button data-test-copy-button
> />
Copy JSON
</CopyButton>
</li> </li>
<li class="action"> <li class="action">
{{#if @wrappedData}} {{#if @wrappedData}}

View file

@ -34,18 +34,15 @@
<Icon @name="minus" /> <Icon @name="minus" />
{{/if}} {{/if}}
</div> </div>
<div class="column {{if @truncateValue 'is-two-thirds is-flex-center' 'is-flex'}}" data-test-value-div={{@label}}> <div class="column is-flex-center {{if @truncateValue 'is-two-thirds'}}" data-test-value-div={{@label}}>
{{#if @addCopyButton}} {{#if @addCopyButton}}
<div class="display-only"> <Hds::Copy::Button
<CopyButton @text="Copy"
@clipboardText={{@value}} @isIconOnly={{true}}
@success={{action (set-flash-message "Data copied!")}} @textToCopy={{@value}}
class="button copy-button is-compact" class="transparent icon-only is-paddingless"
data-test-copy-button data-test-copy-button
> />
<Icon @name="clipboard-copy" aria-label="Copy value" />
</CopyButton>
</div>
{{/if}} {{/if}}
{{#if (has-block)}} {{#if (has-block)}}
{{yield}} {{yield}}
@ -90,18 +87,18 @@
<span class="is-word-break has-text-black" data-test-row-value={{@label}}>{{@value}}</span> <span class="is-word-break has-text-black" data-test-row-value={{@label}}>{{@value}}</span>
</T.Trigger> </T.Trigger>
<T.Content @defaultClass="tool-tip"> <T.Content @defaultClass="tool-tip">
<CopyButton <div class="box is-flex-center">
@clipboardText={{@tooltipText}} {{@tooltipText}}
@success={{action (set-flash-message "Data copied!")}} {{#if @isTooltipCopyable}}
@tagName="div" <Hds::Copy::Button
disabled={{not @isTooltipCopyable}} @text="Copy"
class={{if @isTooltipCopyable "has-pointer"}} @isIconOnly={{true}}
data-test-tooltip-copy @textToCopy={{@tooltipText}}
> class="transparent white-icon"
<div class="box"> data-test-tooltip-copy
{{@tooltipText}} />
</div> {{/if}}
</CopyButton> </div>
</T.Content> </T.Content>
</ToolTip> </ToolTip>
{{else}} {{else}}

View file

@ -28,14 +28,13 @@
</button> </button>
{{/if}} {{/if}}
<div class="toolbar-separator"></div> <div class="toolbar-separator"></div>
<CopyButton <Hds::Copy::Button
class="button is-transparent" @text="Copy"
@clipboardText={{@value}} @isIconOnly={{true}}
@buttonType="button" @textToCopy={{@value}}
@success={{action (set-flash-message "Data copied!")}} class="transparent"
> data-test-copy-button
<Icon @name="clipboard-copy" aria-label="Copy" /> />
</CopyButton>
</ToolbarActions> </ToolbarActions>
</Toolbar> </Toolbar>
</div> </div>

View file

@ -35,15 +35,13 @@
/> />
{{/if}} {{/if}}
{{#if @allowCopy}} {{#if @allowCopy}}
<CopyButton <Hds::Copy::Button
@clipboardText={{@value}} @text="Copy"
@success={{action (set-flash-message "Data copied!")}} @isIconOnly={{true}}
@error={{action (set-flash-message "Error copying data" "danger")}} @textToCopy={{@value}}
class="copy-button button {{if @displayOnly 'is-compact'}}" class="transparent icon-only is-paddingless"
data-test-copy-button data-test-copy-button
> />
<Icon @name="clipboard-copy" aria-label="Copy value" />
</CopyButton>
{{/if}} {{/if}}
{{#if @allowDownload}} {{#if @allowDownload}}
<DownloadButton <DownloadButton

View file

@ -16,10 +16,7 @@
<p class="help has-text-grey has-bottom-margin-xs"> <p class="help has-text-grey has-bottom-margin-xs">
This is a one-time token that will be used to generate the operation token. Please save it. This is a one-time token that will be used to generate the operation token. Please save it.
</p> </p>
<div class="message is-list has-copy-button" tabindex="-1"> <Hds::Copy::Snippet @textToCopy={{this.encodedToken}} data-test-shamir-encoded-token />
<HoverCopyButton @copyValue={{this.encodedToken}} />
<code class="is-word-break" data-test-shamir-encoded-token>{{this.encodedToken}}</code>
</div>
</div> </div>
{{#if this.otp}} {{#if this.otp}}
<div class="has-bottom-margin-xl"> <div class="has-bottom-margin-xl">
@ -29,10 +26,7 @@
<p class="help has-text-grey has-bottom-margin-xs"> <p class="help has-text-grey has-bottom-margin-xs">
This OTP will be used to decode the generated operation token. Please save it. This OTP will be used to decode the generated operation token. Please save it.
</p> </p>
<div class="message is-list has-copy-button" tabindex="-1"> <Hds::Copy::Snippet @textToCopy={{this.otp}} />
<HoverCopyButton @copyValue={{this.otp}} />
<code class="is-word-break">{{this.otp}}</code>
</div>
</div> </div>
{{/if}} {{/if}}
<div class="has-bottom-margin-xl"> <div class="has-bottom-margin-xl">
@ -48,21 +42,18 @@
the operation token. the operation token.
{{/if}} {{/if}}
</p> </p>
<div class="message is-list has-copy-button" tabindex="-1"> {{! template-lint-disable quotes }}
{{! template-lint-disable quotes }} {{#let
{{#let (if
(if this.otp
this.otp (concat 'vault operator generate-root -dr-token -otp="' this.otp '" -decode="' this.encodedToken '"')
(concat 'vault operator generate-root -dr-token -otp="' this.otp '" -decode="' this.encodedToken '"') (concat 'vault operator generate-root -dr-token -otp="<enter your otp here>" -decode="' this.encodedToken '"')
(concat 'vault operator generate-root -dr-token -otp="<enter your otp here>" -decode="' this.encodedToken '"') )
) as |cmd|
as |cmd| }}
}} <CodeSnippet @codeBlock={{cmd}} />
<HoverCopyButton @copyValue={{cmd}} /> {{/let}}
<code class="is-word-break">{{cmd}}</code> {{! template-lint-enable quotes }}
{{/let}}
{{! template-lint-enable quotes }}
</div>
</div> </div>
</div> </div>
<div> <div>

View file

@ -13,18 +13,17 @@
{{#if @otp}} {{#if @otp}}
<Hds::Alert @type="inline" @color="highlight" class="has-bottom-margin-s" data-test-otp-info as |A|> <Hds::Alert @type="inline" @color="highlight" class="has-bottom-margin-s" data-test-otp-info as |A|>
<A.Title>Info</A.Title> <A.Title>Info</A.Title>
<A.Description> <A.Description class="has-bottom-margin-s">
Below is the generated OTP. This will be used to encode the generated Operation Token. Make sure to save this, as Below is the generated OTP. This will be used to encode the generated Operation Token. Make sure to save this, as
you will need it later to decode the Operation Token. you will need it later to decode the Operation Token.
</A.Description> </A.Description>
<A.Description>
<h4 class="hds-alert__title hds-font-weight-semibold">
One Time Password (otp)
</h4>
<Hds::Copy::Snippet data-test-otp @textToCopy={{@otp}} @color="secondary" />
</A.Description>
</Hds::Alert> </Hds::Alert>
<div class="has-background-gray-100 box has-copy-button" tabindex="-1">
<HoverCopyButton @copyValue={{@otp}} />
<h4 class="title is-7 is-marginless">
One Time Password (otp)
</h4>
<code class="is-word-break" data-test-otp>{{@otp}}</code>
</div>
{{/if}} {{/if}}
{{#if (has-block)}} {{#if (has-block)}}
{{yield}} {{yield}}

View file

@ -5,46 +5,37 @@
{{#if this.encoded_token}} {{#if this.encoded_token}}
<div class="box is-marginless is-shadowless"> <div class="box is-marginless is-shadowless">
<div class="message is-list has-copy-button" tabindex="-1"> <div class="message">
<HoverCopyButton @copyValue={{this.encoded_token}} /> <h4 class="title is-7 is-marginless">
<div class="message-body"> Encoded Operation Token
<h4 class="title is-7 is-marginless"> </h4>
Encoded Operation Token <Hds::Copy::Snippet @textToCopy={{this.encoded_token}} />
</h4>
<code class="is-word-break">{{this.encoded_token}}</code>
</div>
</div> </div>
{{#if this.otp}} {{#if this.otp}}
<div class="message is-list has-copy-button" tabindex="-1"> <div class="message">
<HoverCopyButton @copyValue={{this.otp}} /> <h4 class="title is-7 is-marginless">
<div class="message-body"> One Time Password (otp)
<h4 class="title is-7 is-marginless"> </h4>
One Time Password (otp) <Hds::Copy::Snippet @textToCopy={{this.otp}} />
</h4>
<code class="is-word-break">{{this.otp}}</code>
</div>
</div> </div>
{{/if}} {{/if}}
<div class="message is-list has-copy-button" tabindex="-1">
{{! template-lint-disable quotes }} {{! template-lint-disable quotes }}
{{#let {{#let
(if (if
this.otp this.otp
(concat 'vault operator generate-root -otp="' this.otp '" -decode="' this.encoded_token '"') (concat 'vault operator generate-root -otp="' this.otp '" -decode="' this.encoded_token '"')
(concat 'vault operator generate-root -otp="<enter your otp here>" -decode="' this.encoded_token '"') (concat 'vault operator generate-root -otp="<enter your otp here>" -decode="' this.encoded_token '"')
) )
as |cmd| as |cmd|
}} }}
<HoverCopyButton @copyValue={{cmd}} /> <h4 class="title is-7 is-marginless">
<div class="message-body"> DR Operation Token Command
<h4 class="title is-7 is-marginless"> </h4>
DR Operation Token Command <CodeSnippet @codeBlock={{cmd}} />
</h4> {{/let}}
<code class="is-word-break">{{cmd}}</code> {{! template-lint-enable quotes }}
</div>
{{/let}}
{{! template-lint-enable quotes }}
</div>
</div> </div>
<div class="box is-marginless is-shadowless"> <div class="box is-marginless is-shadowless">
<button type="button" class="button" {{action "reset"}}> <button type="button" class="button" {{action "reset"}}>
@ -107,15 +98,12 @@
Below is the base-64 encoded PGP Key that will be used to encrypt the generated Operation Token. Next we'll enter Below is the base-64 encoded PGP Key that will be used to encrypt the generated Operation Token. Next we'll enter
portions of the root key to generate an Operation Token. Click the "Generate Operation Token" button to proceed. portions of the root key to generate an Operation Token. Click the "Generate Operation Token" button to proceed.
</p> </p>
<div class="message is-list has-copy-button" tabindex="-1"> <div class="message">
<HoverCopyButton @copyValue={{this.pgp_key}} /> <h4 class="title is-7 is-marginless">
<div class="message-body"> PGP Key
<h4 class="title is-7 is-marginless"> {{this.pgpKeyFile.filename}}
PGP Key </h4>
{{this.pgpKeyFile.filename}} <Hds::Copy::Snippet @textToCopy={{this.pgp_key}} />
</h4>
<code class="is-word-break">{{this.pgp_key}}</code>
</div>
</div> </div>
</div> </div>
<div class="field is-grouped box is-marginless is-shadowless"> <div class="field is-grouped box is-marginless is-shadowless">
@ -145,19 +133,18 @@
<p> <p>
<Hds::Alert @type="inline" @color="highlight" class="has-bottom-margin-s" as |A|> <Hds::Alert @type="inline" @color="highlight" class="has-bottom-margin-s" as |A|>
<A.Title>Info</A.Title> <A.Title>Info</A.Title>
<A.Description> <A.Description class="has-bottom-margin-s">
Below is the generated OTP. This will be used to encode the generated Operation Token. Make sure to save Below is the generated OTP. This will be used to encode the generated Operation Token. Make sure to save
this, as you will need it later to decode the Operation Token. this, as you will need it later to decode the Operation Token.
</A.Description> </A.Description>
<A.Description>
<h4 class="hds-alert__title hds-font-weight-semibold">
One Time Password (otp)
</h4>
<Hds::Copy::Snippet @textToCopy={{this.otp}} @color="secondary" />
</A.Description>
</Hds::Alert> </Hds::Alert>
</p> </p>
<div class="has-background-gray-100 box has-copy-button" tabindex="-1">
<HoverCopyButton @copyValue={{this.otp}} />
<h4 class="title is-7 is-marginless">
One Time Password (otp)
</h4>
<code class="is-word-break">{{this.otp}}</code>
</div>
{{/if}} {{/if}}
{{#if (has-block)}} {{#if (has-block)}}
{{yield}} {{yield}}

View file

@ -31,30 +31,29 @@
<ToolbarLink @route="credentials.index" @models={{array this.scope this.role}} data-test-kmip-link-back-to-role> <ToolbarLink @route="credentials.index" @models={{array this.scope this.role}} data-test-kmip-link-back-to-role>
Back to role Back to role
</ToolbarLink> </ToolbarLink>
<CopyButton <Hds::Copy::Button
class="toolbar-link" @text="Copy certificate"
@clipboardText={{this.model.certificate}} @textToCopy={{this.model.certificate}}
@success={{action (set-flash-message "Certificate Copied!")}} class="toolbar-link is-flex-center"
data-test-copy-button data-test-copy-button
> />
Copy certificate
<Chevron />
</CopyButton>
</ToolbarActions> </ToolbarActions>
</Toolbar> </Toolbar>
<div class="box is-shadowless is-fullwidth is-sideless"> <div class="box is-shadowless is-fullwidth is-sideless">
<InfoTableRow @label="Serial number" @value={{this.model.id}}> <InfoTableRow @label="Serial number" @value={{this.model.id}}>
<MaskedInput @value={{this.model.id}} @displayOnly={{true}} @allowCopy={{true}} /> <MaskedInput @value={{this.model.id}} @displayOnly={{true}} @allowCopy={{true}} />
</InfoTableRow> </InfoTableRow>
<InfoTableRow @label="Private key" @value={{this.model.privateKey}}> {{#if this.model.privateKey}}
<div class="is-block"> <InfoTableRow @label="Private key" @value={{this.model.privateKey}}>
<Hds::Alert data-test-warning @type="inline" @color="warning" @class="has-bottom-margin-s" as |A|> <div class="is-block">
<A.Title>Warning</A.Title> <Hds::Alert data-test-warning @type="inline" @color="warning" @class="has-bottom-margin-s" as |A|>
<A.Description>You will not be able to access the private key later, so please copy the information below.</A.Description> <A.Title>Warning</A.Title>
</Hds::Alert> <A.Description>You will not be able to access the private key later, so please copy the information below.</A.Description>
<MaskedInput @value={{this.model.privateKey}} @name="Private key" @allowCopy={{true}} @displayOnly={{true}} /> </Hds::Alert>
</div> <MaskedInput @value={{this.model.privateKey}} @name="Private key" @allowCopy={{true}} @displayOnly={{true}} />
</InfoTableRow> </div>
</InfoTableRow>
{{/if}}
<InfoTableRow @label="Certificate" @value={{this.model.certificate}}> <InfoTableRow @label="Certificate" @value={{this.model.certificate}}>
<MaskedInput @value={{this.model.certificate}} @displayOnly={{true}} @allowCopy={{true}} /> <MaskedInput @value={{this.model.certificate}} @displayOnly={{true}} @allowCopy={{true}} />
</InfoTableRow> </InfoTableRow>

View file

@ -16,15 +16,7 @@
<div class="box is-fullwidth is-sideless is-paddingless is-marginless"> <div class="box is-fullwidth is-sideless is-paddingless is-marginless">
{{#each this.paths as |path|}} {{#each this.paths as |path|}}
<InfoTableRow @label={{path.label}} @labelWidth="is-one-third" @helperText={{path.text}} @truncateValue={{true}}> <InfoTableRow @label={{path.label}} @labelWidth="is-one-third" @helperText={{path.text}} @truncateValue={{true}}>
{{! replace with Hds::Copy::Snippet }} <Hds::Copy::Button @text="Copy" @isIconOnly={{true}} @textToCopy={{path.snippet}} class="transparent" />
<CopyButton
class="button is-compact is-transparent level-right"
@clipboardText={{path.snippet}}
@buttonType="button"
@success={{fn (set-flash-message (concat path.label " copied!"))}}
>
<Icon @name="clipboard-copy" aria-label="Copy" />
</CopyButton>
<code class="is-flex-1 text-overflow-ellipsis has-left-margin-s"> <code class="is-flex-1 text-overflow-ellipsis has-left-margin-s">
{{path.snippet}} {{path.snippet}}
</code> </code>

View file

@ -81,16 +81,12 @@
</div> </div>
</section> </section>
<footer class="modal-card-foot"> <footer class="modal-card-foot">
<CopyButton <Hds::Copy::Button
class="button is-primary copy-close" @text="Copy & Close"
data-test-button="modal-copy-close" @textToCopy={{this.token}}
@clipboardText={{this.token}} class="primary"
@buttonType="button" {{on "click" (action "copyClose" "Token copied!")}}
@type="copy" />
@success={{action "copyClose" "Token copied!"}}
>
Copy &amp; Close
</CopyButton>
</footer> </footer>
</Modal> </Modal>
{{/if}} {{/if}}

View file

@ -65,7 +65,7 @@
"@ember/test-waiters": "^3.0.0", "@ember/test-waiters": "^3.0.0",
"@glimmer/component": "^1.1.2", "@glimmer/component": "^1.1.2",
"@glimmer/tracking": "^1.1.2", "@glimmer/tracking": "^1.1.2",
"@hashicorp/ember-flight-icons": "3.0.5", "@hashicorp/ember-flight-icons": "^3.0.9",
"@hashicorp/structure-icons": "^1.3.0", "@hashicorp/structure-icons": "^1.3.0",
"@icholy/duration": "^5.1.0", "@icholy/duration": "^5.1.0",
"@tsconfig/ember": "^1.0.1", "@tsconfig/ember": "^1.0.1",
@ -125,7 +125,6 @@
"ember-cli": "~4.12.1", "ember-cli": "~4.12.1",
"ember-cli-autoprefixer": "^0.8.1", "ember-cli-autoprefixer": "^0.8.1",
"ember-cli-babel": "^7.26.11", "ember-cli-babel": "^7.26.11",
"ember-cli-clipboard": "0.16.0",
"ember-cli-content-security-policy": "2.0.3", "ember-cli-content-security-policy": "2.0.3",
"ember-cli-dependency-checker": "^3.3.1", "ember-cli-dependency-checker": "^3.3.1",
"ember-cli-deprecation-workflow": "^2.1.0", "ember-cli-deprecation-workflow": "^2.1.0",
@ -249,7 +248,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@hashicorp/design-system-components": "2.7.0", "@hashicorp/design-system-components": "^2.9.0",
"handlebars": "4.7.7", "handlebars": "4.7.7",
"highlight.js": "^10.4.1", "highlight.js": "^10.4.1",
"node-notifier": "^8.0.1", "node-notifier": "^8.0.1",

View file

@ -1,43 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, settled } from '@ember/test-helpers';
import { create } from 'ember-cli-page-object';
import hbs from 'htmlbars-inline-precompile';
import copyButton from 'vault/tests/pages/components/hover-copy-button';
const component = create(copyButton);
module('Integration | Component | hover copy button', function (hooks) {
setupRenderingTest(hooks);
// ember-cli-clipboard helpers don't like the new style
test('it shows success message in tooltip', async function (assert) {
await render(hbs`
<div class="has-copy-button" tabindex="-1">
<HoverCopyButton @copyValue="foo" />
</div>
`);
await component.focusContainer();
await settled();
assert.ok(component.buttonIsVisible);
await component.mouseEnter();
await settled();
assert.strictEqual(component.tooltipText, 'Copy', 'shows copy');
});
test('it has the correct class when alwaysShow is true', async function (assert) {
await render(hbs`
<HoverCopyButton
@copyValue="foo"
@alwaysShow={{true}}
/>
`);
await render(hbs`{{hover-copy-button alwaysShow=true copyValue=this.copyValue}}`);
assert.ok(component.buttonIsVisible);
assert.ok(component.wrapperClass.includes('hover-copy-button-static'));
});
});

View file

@ -76,7 +76,7 @@ module('Integration | Component | InfoTableRow', function (hooks) {
}); });
test('it should copy tooltip', async function (assert) { test('it should copy tooltip', async function (assert) {
assert.expect(4); assert.expect(3);
this.set('isCopyable', false); this.set('isCopyable', false);
@ -91,13 +91,12 @@ module('Integration | Component | InfoTableRow', function (hooks) {
await triggerEvent('[data-test-value-div="test label"] .ember-basic-dropdown-trigger', 'mouseenter'); await triggerEvent('[data-test-value-div="test label"] .ember-basic-dropdown-trigger', 'mouseenter');
assert.dom('[data-test-tooltip-copy]').hasAttribute('disabled', '', 'Tooltip copy button is disabled'); assert.dom('[data-test-tooltip-copy]').doesNotExist('Tooltip has no copy button');
this.set('isCopyable', true);
assert.dom('[data-test-tooltip-copy]').exists('Tooltip has copy button');
assert assert
.dom('[data-test-tooltip-copy]') .dom('[data-test-tooltip-copy]')
.doesNotHaveClass('has-pointer', 'Pointer class not applied when disabled'); .hasAttribute('data-clipboard-text', 'Foo bar', 'Copy button will copy the tooltip text');
this.set('isCopyable', true);
assert.dom('[data-test-tooltip-copy]').doesNotHaveAttribute('disabled', 'Tooltip copy button is enabled');
assert.dom('[data-test-tooltip-copy]').hasClass('has-pointer', 'Pointer class applied to copy button');
}); });
test('it renders a string with no link if isLink is true and the item type is not an array.', async function (assert) { test('it renders a string with no link if isLink is true and the item type is not an array.', async function (assert) {
@ -138,13 +137,13 @@ module('Integration | Component | InfoTableRow', function (hooks) {
this.set('value', ''); this.set('value', '');
this.set('label', LABEL); this.set('label', LABEL);
assert.dom('div.column.is-flex .flight-icon').exists('Renders a dash (-) for empty string value'); assert.dom('div.column.is-flex-center .flight-icon').exists('Renders a dash (-) for empty string value');
this.set('value', null); this.set('value', null);
assert.dom('div.column.is-flex .flight-icon').exists('Renders a dash (-) for null value'); assert.dom('div.column.is-flex-center .flight-icon').exists('Renders a dash (-) for null value');
this.set('value', undefined); this.set('value', undefined);
assert.dom('div.column.is-flex .flight-icon').exists('Renders a dash (-) for undefined value'); assert.dom('div.column.is-flex-center .flight-icon').exists('Renders a dash (-) for undefined value');
this.set('default', DEFAULT); this.set('default', DEFAULT);
assert.dom('[data-test-value-div]').hasText(DEFAULT, 'Renders default text if value is empty'); assert.dom('[data-test-value-div]').hasText(DEFAULT, 'Renders default text if value is empty');

View file

@ -41,6 +41,7 @@ module('Integration | Component | json-editor', function (hooks) {
assert.strictEqual(component.title, 'Test title', 'renders the provided title'); assert.strictEqual(component.title, 'Test title', 'renders the provided title');
assert.true(component.hasToolbar, 'renders the toolbar'); assert.true(component.hasToolbar, 'renders the toolbar');
assert.true(component.hasCopyButton, 'renders the copy button');
assert.true(component.hasJSONEditor, 'renders the code mirror modifier'); assert.true(component.hasJSONEditor, 'renders the code mirror modifier');
assert.ok(component.canEdit, 'json editor can be edited'); assert.ok(component.canEdit, 'json editor can be edited');
}); });

View file

@ -125,34 +125,4 @@ module('Integration | Component | masked input', function (hooks) {
.dom('[data-test-icon="minus"]') .dom('[data-test-icon="minus"]')
.exists('shows minus icon when unmasked because value is empty string'); .exists('shows minus icon when unmasked because value is empty string');
}); });
test('it shows "success" flash message when the value is successfully copied', async function (assert) {
await render(hbs`
<MaskedInput
@name="key"
@value="value"
@displayOnly={{true}}
@allowCopy={{true}}
/>
`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
assert.ok(component.copyButtonIsPresent);
await component.copyValue();
assert.ok(this.flashSuccessSpy.calledWith('Data copied!'), 'Renders correct flash message');
});
test('it shows "danger" flash message when the value fails to be copied (no value)', async function (assert) {
await render(hbs`
<MaskedInput
@name="key"
@value=""
@displayOnly={{true}}
@allowCopy={{true}}
/>
`);
assert.dom('[data-test-masked-input]').exists('shows masked input');
assert.ok(component.copyButtonIsPresent);
await component.copyValue();
assert.ok(this.flashDangerSpy.calledWith('Error copying data'), 'Renders correct flash message');
});
}); });

View file

@ -154,10 +154,20 @@ module('Integration | Component | oidc/scope-form', function (hooks) {
}); });
test('it should show example template modal', async function (assert) { test('it should show example template modal', async function (assert) {
assert.expect(6); assert.expect(8);
this.model = this.store.createRecord('oidc/scope'); this.model = this.store.createRecord('oidc/scope');
// formatting here is purposeful so that it matches formatting in the template modal
const exampleTemplate = `{
"username": {{identity.entity.aliases.$MOUNT_ACCESSOR.name}},
"contact": {
"email": {{identity.entity.metadata.email}},
"phone_number": {{identity.entity.metadata.phone_number}}
},
"groups": {{identity.entity.groups.names}}
}`;
await render(hbs` await render(hbs`
<Oidc::ScopeForm <Oidc::ScopeForm
@model={{this.model}} @model={{this.model}}
@ -172,8 +182,12 @@ module('Integration | Component | oidc/scope-form', function (hooks) {
assert.dom('[data-test-modal-div]').hasClass('is-active', 'Modal is shown'); assert.dom('[data-test-modal-div]').hasClass('is-active', 'Modal is shown');
assert.dom('[data-test-modal-title]').hasText('Scope template', 'Modal title renders'); assert.dom('[data-test-modal-title]').hasText('Scope template', 'Modal title renders');
assert assert
.dom('[data-test-modal-copy]') .dom('[data-test-modal-text]')
.hasText('Example of a JSON template for scopes:', 'Modal copy renders'); .hasText('Example of a JSON template for scopes:', 'Modal text renders');
assert.dom('[data-test-copy-button]').exists('Modal copy button renders');
assert
.dom('[data-test-modal-div] [data-test-copy-button]')
.hasAttribute('data-clipboard-text', exampleTemplate, 'Modal copy button copies the example template');
assert.dom('.cm-string').hasText('"username"', 'Example template json renders'); assert.dom('.cm-string').hasText('"username"', 'Example template json renders');
await click('[data-test-close-modal]'); await click('[data-test-close-modal]');
assert.dom('[data-test-modal-div]').doesNotHaveClass('is-active', 'Modal is hidden'); assert.dom('[data-test-modal-div]').doesNotHaveClass('is-active', 'Modal is hidden');

View file

@ -280,8 +280,8 @@ module('Integration | Component | transit key actions', function (hooks) {
await click('button[type="submit"]'); await click('button[type="submit"]');
assert.dom('.modal.is-active').exists('Modal opens after export'); assert.dom('.modal.is-active').exists('Modal opens after export');
assert.deepEqual( assert.deepEqual(
find('.modal [data-test-encrypted-value="export"]').innerText, JSON.parse(find('.modal [data-test-encrypted-value="export"]').innerText),
JSON.stringify(response, null, 2), response,
'prints json response' 'prints json response'
); );
}); });
@ -296,8 +296,8 @@ module('Integration | Component | transit key actions', function (hooks) {
await click('button[type="submit"]'); await click('button[type="submit"]');
assert.dom('.modal.is-active').exists('Modal opens after export'); assert.dom('.modal.is-active').exists('Modal opens after export');
assert.deepEqual( assert.deepEqual(
find('.modal [data-test-encrypted-value="export"]').innerText, JSON.parse(find('.modal [data-test-encrypted-value="export"]').innerText),
JSON.stringify(response, null, 2), response,
'prints json response' 'prints json response'
); );
assert.deepEqual( assert.deepEqual(

View file

@ -1,24 +0,0 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { attribute, clickable, isVisible, focusable, text } from 'ember-cli-page-object';
import { triggerEvent, focus } from '@ember/test-helpers';
export default {
async focusContainer() {
await focus('.has-copy-button');
},
tooltipText: text('[data-test-hover-copy-tooltip-text]', {
testContainer: '#ember-testing',
}),
wrapperClass: attribute('class', '[data-test-hover-copy]'),
buttonIsVisible: isVisible('[data-test-hover-copy-button]'),
click: clickable('[data-test-hover-copy-button]'),
focus: focusable('[data-test-hover-copy-button]'),
async mouseEnter() {
await triggerEvent('[data-test-tooltip-trigger]', 'mouseenter');
},
};

View file

@ -8,6 +8,7 @@ import { isPresent, notHasClass, text } from 'ember-cli-page-object';
export default { export default {
title: text('[data-test-component=json-editor-title]'), title: text('[data-test-component=json-editor-title]'),
hasToolbar: isPresent('[data-test-component=json-editor-toolbar]'), hasToolbar: isPresent('[data-test-component=json-editor-toolbar]'),
hasCopyButton: isPresent('[data-test-copy-button]'),
hasJSONEditor: isPresent('[data-test-component="code-mirror-modifier"]'), hasJSONEditor: isPresent('[data-test-component="code-mirror-modifier"]'),
canEdit: notHasClass('readonly-codemirror'), canEdit: notHasClass('readonly-codemirror'),
}; };

View file

@ -8,7 +8,7 @@ import { text, collection } from 'ember-cli-page-object';
export default { export default {
detailRows: collection('[data-test-detail-row]', { detailRows: collection('[data-test-detail-row]', {
rowName: text('[data-test-row-label]'), rowName: text('[data-test-row-label]'),
rowValue: text('.column.is-flex'), rowValue: text('.column.is-flex-center'),
}), }),
featureRows: collection('[data-test-feature-row]', { featureRows: collection('[data-test-feature-row]', {
featureName: text('[data-test-row-label]'), featureName: text('[data-test-row-label]'),

View file

@ -4392,19 +4392,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ember/render-modifiers@npm:^1.0.2 || ^2.0.0, @ember/render-modifiers@npm:^2.0.2, @ember/render-modifiers@npm:^2.0.4":
version: 2.0.4
resolution: "@ember/render-modifiers@npm:2.0.4"
dependencies:
"@embroider/macros": ^1.0.0
ember-cli-babel: ^7.26.11
ember-modifier-manager-polyfill: ^1.2.0
peerDependencies:
ember-source: ^3.8 || 4
checksum: 6186a013349273f9eb0339a5b2ab7ccc7b9e6429d83b8cabba2842dfc35bd4b77b66979c2f2c25b062a7cdd359c6a500df27154880ac5f04a3ffa52ca6e343d6
languageName: node
linkType: hard
"@ember/render-modifiers@npm:^2.0.0, @ember/render-modifiers@npm:^2.0.5": "@ember/render-modifiers@npm:^2.0.0, @ember/render-modifiers@npm:^2.0.5":
version: 2.0.5 version: 2.0.5
resolution: "@ember/render-modifiers@npm:2.0.5" resolution: "@ember/render-modifiers@npm:2.0.5"
@ -4418,6 +4405,19 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ember/render-modifiers@npm:^2.0.2, @ember/render-modifiers@npm:^2.0.4":
version: 2.0.4
resolution: "@ember/render-modifiers@npm:2.0.4"
dependencies:
"@embroider/macros": ^1.0.0
ember-cli-babel: ^7.26.11
ember-modifier-manager-polyfill: ^1.2.0
peerDependencies:
ember-source: ^3.8 || 4
checksum: 6186a013349273f9eb0339a5b2ab7ccc7b9e6429d83b8cabba2842dfc35bd4b77b66979c2f2c25b062a7cdd359c6a500df27154880ac5f04a3ffa52ca6e343d6
languageName: node
linkType: hard
"@ember/string@npm:^3.0.1": "@ember/string@npm:^3.0.1":
version: 3.1.1 version: 3.1.1
resolution: "@ember/string@npm:3.1.1" resolution: "@ember/string@npm:3.1.1"
@ -4457,6 +4457,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ember/test-waiters@npm:^3.0.2":
version: 3.0.2
resolution: "@ember/test-waiters@npm:3.0.2"
dependencies:
calculate-cache-key-for-tree: ^2.0.0
ember-cli-babel: ^7.26.6
ember-cli-version-checker: ^5.1.2
semver: ^7.3.5
checksum: 4ad673fd6c2edc45d7fe378c318dd7f86eabb74eabded5e36b073baa580e2fa2cbb74b52037a2af94a2de98777335129d236b9a33bd33efd30927b0f5e706eaf
languageName: node
linkType: hard
"@embroider/addon-shim@npm:^1.0.0, @embroider/addon-shim@npm:^1.2.0, @embroider/addon-shim@npm:^1.5.0, @embroider/addon-shim@npm:^1.8.4": "@embroider/addon-shim@npm:^1.0.0, @embroider/addon-shim@npm:^1.2.0, @embroider/addon-shim@npm:^1.5.0, @embroider/addon-shim@npm:^1.8.4":
version: 1.8.4 version: 1.8.4
resolution: "@embroider/addon-shim@npm:1.8.4" resolution: "@embroider/addon-shim@npm:1.8.4"
@ -4965,56 +4977,58 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@hashicorp/design-system-components@npm:2.7.0": "@hashicorp/design-system-components@npm:^2.9.0":
version: 2.7.0 version: 2.9.0
resolution: "@hashicorp/design-system-components@npm:2.7.0" resolution: "@hashicorp/design-system-components@npm:2.9.0"
dependencies: dependencies:
"@ember/render-modifiers": ^2.0.5 "@ember/render-modifiers": ^2.0.5
"@hashicorp/design-system-tokens": ^1.5.0 "@ember/test-waiters": ^3.0.2
"@hashicorp/ember-flight-icons": ^3.0.5 "@hashicorp/design-system-tokens": ^1.7.0
"@hashicorp/ember-flight-icons": ^3.0.9
dialog-polyfill: ^0.5.6 dialog-polyfill: ^0.5.6
ember-a11y-refocus: ^3.0.2 ember-a11y-refocus: ^3.0.2
ember-auto-import: ^2.6.0 ember-auto-import: ^2.6.3
ember-cached-decorator-polyfill: ^0.1.4 ember-cached-decorator-polyfill: ^0.1.4
ember-cli-babel: ^7.26.11 ember-cli-babel: ^7.26.11
ember-cli-clipboard: ^1.0.0
ember-cli-htmlbars: ^6.2.0 ember-cli-htmlbars: ^6.2.0
ember-cli-sass: ^10.0.1 ember-cli-sass: ^10.0.1
ember-composable-helpers: ^4.5.0 ember-composable-helpers: ^4.5.0
ember-focus-trap: ^1.0.1 ember-focus-trap: ^1.0.2
ember-keyboard: ^8.1.0 ember-keyboard: ^8.2.0
ember-named-blocks-polyfill: ^0.2.5 ember-named-blocks-polyfill: ^0.2.5
ember-stargate: ^0.4.3 ember-stargate: ^0.4.3
ember-style-modifier: ^0.8.0 ember-style-modifier: ^3.0.1
ember-truth-helpers: ^3.0.0 ember-truth-helpers: ^3.1.1
sass: ^1.58.3 sass: ^1.62.1
tippy.js: ^6.3.7 tippy.js: ^6.3.7
checksum: e100910ffd1b5e5e900c5fccf344b77768b69b847d1e588c23a527fe16134ae9be75c34047a37b3300dc303671675520e3fd4694340f8386bb7ff73129f5ca54 checksum: b7fb3026f6c73f370dc34032d57b292081e5f3a89c16d5a884e9ce778fe77173c9a243ebe6bff76c4eadc0ebd2954169ab56eb181d504ac1204be796a72760cf
languageName: node languageName: node
linkType: hard linkType: hard
"@hashicorp/design-system-tokens@npm:^1.5.0": "@hashicorp/design-system-tokens@npm:^1.7.0":
version: 1.5.0 version: 1.7.0
resolution: "@hashicorp/design-system-tokens@npm:1.5.0" resolution: "@hashicorp/design-system-tokens@npm:1.7.0"
checksum: 79b8f823953f1de7a715203291b96d0c74d9ab10ad38c1f4664cfd7c1ed014ef2f7534a8e9dc20778d1c9a29b8c9a340e2fb84070639c91f637f5348f8f694f2 checksum: fafddf1f4534d34dbe03ee3345064ddb19e06314a9a8b5fed074cc1b768ab56c72b477ab9a75a036ce521d883bf7e09e0509ecdc284556a9ffae418dcac8adbc
languageName: node languageName: node
linkType: hard linkType: hard
"@hashicorp/ember-flight-icons@npm:3.0.5, @hashicorp/ember-flight-icons@npm:^3.0.5": "@hashicorp/ember-flight-icons@npm:^3.0.9":
version: 3.0.5 version: 3.0.9
resolution: "@hashicorp/ember-flight-icons@npm:3.0.5" resolution: "@hashicorp/ember-flight-icons@npm:3.0.9"
dependencies: dependencies:
"@hashicorp/flight-icons": ^2.13.1 "@hashicorp/flight-icons": ^2.17.0
ember-auto-import: ^2.6.0 ember-auto-import: ^2.6.3
ember-cli-babel: ^7.26.11 ember-cli-babel: ^7.26.11
ember-cli-htmlbars: ^6.1.0 ember-cli-htmlbars: ^6.2.0
checksum: b18bcd8765e6df59c4bdd6dd584fdaac8f40c7fcd59980092e89a82167178d827895f05867ae6b2005f2513300cff5f6b60b65606567ca8d9c422f18b14bbc79 checksum: b909a45059fbb8bcabe59103a6fa323b0baee4f09ad97d9c7f92251da680704724de469031b3ea83517026ecd4c6754155f9d5f3160640ffac83841c5e0a00e0
languageName: node languageName: node
linkType: hard linkType: hard
"@hashicorp/flight-icons@npm:^2.13.1": "@hashicorp/flight-icons@npm:^2.17.0":
version: 2.13.1 version: 2.17.0
resolution: "@hashicorp/flight-icons@npm:2.13.1" resolution: "@hashicorp/flight-icons@npm:2.17.0"
checksum: 590e30e346c9fa0a9bfbe8376300e73c58d0fa95f108c3f67c0795c05576ca39f3beb971bcd20f90f78c7978bfbf2c7d5fc6e5a5dd1efc029e7afdd9f87a3a19 checksum: 7df3e08ac8d814a661ff39a81421d586279091c83a742434dfc24a7f5381d000bbfa9a6b10aefbe138e2543a17e0643aadea8fe1004128e989c59dd74bfdc9e6
languageName: node languageName: node
linkType: hard linkType: hard
@ -10456,7 +10470,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"clipboard@npm:^2.0.6": "clipboard@npm:^2.0.11":
version: 2.0.11 version: 2.0.11
resolution: "clipboard@npm:2.0.11" resolution: "clipboard@npm:2.0.11"
dependencies: dependencies:
@ -12333,6 +12347,20 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-arg-types@npm:^1.0.0":
version: 1.0.0
resolution: "ember-arg-types@npm:1.0.0"
dependencies:
"@embroider/macros": ^1.8.1
ember-auto-import: ^2.4.2
ember-cli-babel: ^7.26.11
ember-cli-typescript: ^5.1.1
ember-get-config: ^2.1.1
prop-types: ^15.7.2
checksum: 8313a4a2644daeedcbd6d097b9cbd1d19045117b76814d33552f207d33111454379c38cdcfc478cdca85c0b956727371ba4bee83cc89cdb438463a0b2f5e72bd
languageName: node
linkType: hard
"ember-asset-loader@npm:^0.6.1": "ember-asset-loader@npm:^0.6.1":
version: 0.6.1 version: 0.6.1
resolution: "ember-asset-loader@npm:0.6.1" resolution: "ember-asset-loader@npm:0.6.1"
@ -12358,7 +12386,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-auto-import@npm:2.6.3, ember-auto-import@npm:^2.4.2, ember-auto-import@npm:^2.4.3, ember-auto-import@npm:^2.5.0": "ember-auto-import@npm:2.6.3, ember-auto-import@npm:^2.4.2, ember-auto-import@npm:^2.4.3, ember-auto-import@npm:^2.5.0, ember-auto-import@npm:^2.6.3":
version: 2.6.3 version: 2.6.3
resolution: "ember-auto-import@npm:2.6.3" resolution: "ember-auto-import@npm:2.6.3"
dependencies: dependencies:
@ -12397,43 +12425,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-auto-import@npm:^1.11.3":
version: 1.12.0
resolution: "ember-auto-import@npm:1.12.0"
dependencies:
"@babel/core": ^7.1.6
"@babel/preset-env": ^7.10.2
"@babel/traverse": ^7.1.6
"@babel/types": ^7.1.6
"@embroider/core": ^0.33.0
babel-core: ^6.26.3
babel-loader: ^8.0.6
babel-plugin-syntax-dynamic-import: ^6.18.0
babylon: ^6.18.0
broccoli-debug: ^0.6.4
broccoli-node-api: ^1.7.0
broccoli-plugin: ^4.0.0
broccoli-source: ^3.0.0
debug: ^3.1.0
ember-cli-babel: ^7.0.0
enhanced-resolve: ^4.0.0
fs-extra: ^6.0.1
fs-tree-diff: ^2.0.0
handlebars: ^4.3.1
js-string-escape: ^1.0.1
lodash: ^4.17.19
mkdirp: ^0.5.1
resolve-package-path: ^3.1.0
rimraf: ^2.6.2
semver: ^7.3.4
symlink-or-copy: ^1.2.0
typescript-memoize: ^1.0.0-alpha.3
walk-sync: ^0.3.3
webpack: ^4.43.0
checksum: 689de6088854855c7eb50d882a81fc9ee3efd1671ddd8aea35a7d6ef0db8e08d211d156b63390da4fd98518d32ad2a3f9ed9be6f25810311a9011604f10b3c85
languageName: node
linkType: hard
"ember-auto-import@npm:^1.12.0": "ember-auto-import@npm:^1.12.0":
version: 1.12.1 version: 1.12.1
resolution: "ember-auto-import@npm:1.12.1" resolution: "ember-auto-import@npm:1.12.1"
@ -12546,44 +12537,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-auto-import@npm:^2.6.0":
version: 2.6.1
resolution: "ember-auto-import@npm:2.6.1"
dependencies:
"@babel/core": ^7.16.7
"@babel/plugin-proposal-class-properties": ^7.16.7
"@babel/plugin-proposal-decorators": ^7.16.7
"@babel/preset-env": ^7.16.7
"@embroider/macros": ^1.0.0
"@embroider/shared-internals": ^2.0.0
babel-loader: ^8.0.6
babel-plugin-ember-modules-api-polyfill: ^3.5.0
babel-plugin-htmlbars-inline-precompile: ^5.2.1
babel-plugin-syntax-dynamic-import: ^6.18.0
broccoli-debug: ^0.6.4
broccoli-funnel: ^3.0.8
broccoli-merge-trees: ^4.2.0
broccoli-plugin: ^4.0.0
broccoli-source: ^3.0.0
css-loader: ^5.2.0
debug: ^4.3.1
fs-extra: ^10.0.0
fs-tree-diff: ^2.0.0
handlebars: ^4.3.1
js-string-escape: ^1.0.1
lodash: ^4.17.19
mini-css-extract-plugin: ^2.5.2
parse5: ^6.0.1
resolve: ^1.20.0
resolve-package-path: ^4.0.3
semver: ^7.3.4
style-loader: ^2.0.0
typescript-memoize: ^1.0.0-alpha.3
walk-sync: ^3.0.0
checksum: 46c55add57a58aecd772c8a7f038afd458e362011301c99766d9a11e83121d96b5170fe48af8e12460b64aaebf4242f0a6f8d21ff152925b62f8e595f034c1b1
languageName: node
linkType: hard
"ember-basic-dropdown@npm:6.0.1": "ember-basic-dropdown@npm:6.0.1":
version: 6.0.1 version: 6.0.1
resolution: "ember-basic-dropdown@npm:6.0.1" resolution: "ember-basic-dropdown@npm:6.0.1"
@ -12722,16 +12675,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-cli-clipboard@npm:0.16.0": "ember-cli-clipboard@npm:^1.0.0":
version: 0.16.0 version: 1.0.0
resolution: "ember-cli-clipboard@npm:0.16.0" resolution: "ember-cli-clipboard@npm:1.0.0"
dependencies: dependencies:
"@ember/render-modifiers": ^1.0.2 || ^2.0.0 clipboard: ^2.0.11
clipboard: ^2.0.6 ember-arg-types: ^1.0.0
ember-auto-import: ^1.11.3 ember-auto-import: ^2.4.2
ember-cli-babel: ^7.26.6 ember-cli-babel: ^7.26.11
ember-cli-htmlbars: ^5.7.1 ember-cli-htmlbars: ^6.1.0
checksum: dea292fb8116d657cc2ac00695c7cdfc6fd71db3ff444b8418a3bdb641165d632e4281e06eb6fabfb82a58eb3a3ed5ea3e861539961501bb141725df7dc75604 ember-modifier: ^3.2.7
prop-types: ^15.8.1
checksum: 448891dcd9db44dfd6621434a5158a226a7cf572fd6359b08c7f486bdeb6380dedb031e21bdad12e9db78b422a365b26e98160c472fb6605cd0efe9936cc037c
languageName: node languageName: node
linkType: hard linkType: hard
@ -13231,7 +13186,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-cli-typescript@npm:^5.2.1": "ember-cli-typescript@npm:^5.1.1, ember-cli-typescript@npm:^5.2.1":
version: 5.2.1 version: 5.2.1
resolution: "ember-cli-typescript@npm:5.2.1" resolution: "ember-cli-typescript@npm:5.2.1"
dependencies: dependencies:
@ -13629,13 +13584,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-focus-trap@npm:^1.0.1": "ember-focus-trap@npm:^1.0.2":
version: 1.0.1 version: 1.0.2
resolution: "ember-focus-trap@npm:1.0.1" resolution: "ember-focus-trap@npm:1.0.2"
dependencies: dependencies:
"@embroider/addon-shim": ^1.0.0 "@embroider/addon-shim": ^1.0.0
focus-trap: ^6.7.1 focus-trap: ^6.7.1
checksum: 1c4b218b0991b3c90411733cf578aa59cc1b7b08ba7654d2ac9540218c07f8c2879ed98c6472c9dea813863500e9dc3279d517ac422d4861a4e4442a1b651e0e checksum: 1940405edcbff3997eb3d9f15314ded20f676e25a07adee5e306c0816ed0743849798c5bd69c1e7e35a5b32c44d0b4995a2d46cc14adc97eab899167fc51a968
languageName: node languageName: node
linkType: hard linkType: hard
@ -13650,7 +13605,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-get-config@npm:^1.0.2 || ^2.0.0": "ember-get-config@npm:^1.0.2 || ^2.0.0, ember-get-config@npm:^2.1.1":
version: 2.1.1 version: 2.1.1
resolution: "ember-get-config@npm:2.1.1" resolution: "ember-get-config@npm:2.1.1"
dependencies: dependencies:
@ -13681,7 +13636,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-keyboard@npm:^8.1.0": "ember-keyboard@npm:^8.2.0":
version: 8.2.0 version: 8.2.0
resolution: "ember-keyboard@npm:8.2.0" resolution: "ember-keyboard@npm:8.2.0"
dependencies: dependencies:
@ -13780,7 +13735,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-modifier@npm:^4.1.0": "ember-modifier@npm:^3.2.7 || ^4.0.0, ember-modifier@npm:^4.1.0":
version: 4.1.0 version: 4.1.0
resolution: "ember-modifier@npm:4.1.0" resolution: "ember-modifier@npm:4.1.0"
dependencies: dependencies:
@ -14048,6 +14003,19 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-style-modifier@npm:^3.0.1":
version: 3.0.1
resolution: "ember-style-modifier@npm:3.0.1"
dependencies:
ember-auto-import: ^2.5.0
ember-cli-babel: ^7.26.11
ember-modifier: ^3.2.7 || ^4.0.0
peerDependencies:
"@ember/string": ^3.0.1
checksum: 093a9affaaa7b3f1c782fa46616bd3f9a02f518c3eff22f1f4c2582f2411cc9d1eecb95d483aaeabf6ce050d95ff928201cd5287e950027b96cbe702e56ae68d
languageName: node
linkType: hard
"ember-svg-jar@npm:2.4.0": "ember-svg-jar@npm:2.4.0":
version: 2.4.0 version: 2.4.0
resolution: "ember-svg-jar@npm:2.4.0" resolution: "ember-svg-jar@npm:2.4.0"
@ -14199,7 +14167,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ember-truth-helpers@npm:^3.0.0": "ember-truth-helpers@npm:^3.0.0, ember-truth-helpers@npm:^3.1.1":
version: 3.1.1 version: 3.1.1
resolution: "ember-truth-helpers@npm:3.1.1" resolution: "ember-truth-helpers@npm:3.1.1"
dependencies: dependencies:
@ -19281,7 +19249,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"loose-envify@npm:^1.0.0": "loose-envify@npm:^1.0.0, loose-envify@npm:^1.4.0":
version: 1.4.0 version: 1.4.0
resolution: "loose-envify@npm:1.4.0" resolution: "loose-envify@npm:1.4.0"
dependencies: dependencies:
@ -22003,6 +21971,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
version: 15.8.1
resolution: "prop-types@npm:15.8.1"
dependencies:
loose-envify: ^1.4.0
object-assign: ^4.1.1
react-is: ^16.13.1
checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459
languageName: node
linkType: hard
"proper-lockfile@npm:^4.1.2": "proper-lockfile@npm:^4.1.2":
version: 4.1.2 version: 4.1.2
resolution: "proper-lockfile@npm:4.1.2" resolution: "proper-lockfile@npm:4.1.2"
@ -22261,6 +22240,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"react-is@npm:^16.13.1":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f
languageName: node
linkType: hard
"read-pkg-up@npm:^8.0.0": "read-pkg-up@npm:^8.0.0":
version: 8.0.0 version: 8.0.0
resolution: "read-pkg-up@npm:8.0.0" resolution: "read-pkg-up@npm:8.0.0"
@ -23309,6 +23295,19 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"sass@npm:^1.62.1":
version: 1.65.1
resolution: "sass@npm:1.65.1"
dependencies:
chokidar: ">=3.0.0 <4.0.0"
immutable: ^4.0.0
source-map-js: ">=0.6.2 <2.0.0"
bin:
sass: sass.js
checksum: 33e325fc80cd07489992e0814cd4929496f87493ffe78c423c2dbafa5746a574e6f3bde20c2a3e4ea47b16ee3d6bc5afcf1d36b405227b829d6c4c9ddcc7f8e2
languageName: node
linkType: hard
"sax@npm:~1.2.4": "sax@npm:~1.2.4":
version: 1.2.4 version: 1.2.4
resolution: "sax@npm:1.2.4" resolution: "sax@npm:1.2.4"
@ -25919,8 +25918,8 @@ __metadata:
"@ember/test-waiters": ^3.0.0 "@ember/test-waiters": ^3.0.0
"@glimmer/component": ^1.1.2 "@glimmer/component": ^1.1.2
"@glimmer/tracking": ^1.1.2 "@glimmer/tracking": ^1.1.2
"@hashicorp/design-system-components": 2.7.0 "@hashicorp/design-system-components": ^2.9.0
"@hashicorp/ember-flight-icons": 3.0.5 "@hashicorp/ember-flight-icons": ^3.0.9
"@hashicorp/structure-icons": ^1.3.0 "@hashicorp/structure-icons": ^1.3.0
"@icholy/duration": ^5.1.0 "@icholy/duration": ^5.1.0
"@tsconfig/ember": ^1.0.1 "@tsconfig/ember": ^1.0.1
@ -25980,7 +25979,6 @@ __metadata:
ember-cli: ~4.12.1 ember-cli: ~4.12.1
ember-cli-autoprefixer: ^0.8.1 ember-cli-autoprefixer: ^0.8.1
ember-cli-babel: ^7.26.11 ember-cli-babel: ^7.26.11
ember-cli-clipboard: 0.16.0
ember-cli-content-security-policy: 2.0.3 ember-cli-content-security-policy: 2.0.3
ember-cli-dependency-checker: ^3.3.1 ember-cli-dependency-checker: ^3.3.1
ember-cli-deprecation-workflow: ^2.1.0 ember-cli-deprecation-workflow: ^2.1.0