mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 03:27:54 +00:00
Ui/redesign delete confirmation (#7271)
* add initial Confirm component to secrets list page * use ember-wormholes to render confirmation message * use maybe-in-element instead of ember-wormhole * hide overlay initially * animate confirm overlay left and right on click * hide overlay in the DOM to properly set height * adjust height when showing/hiding confirm-overlay * disable confirmation buttons until trigger has been rendered * adjust height of confirm-wrapper instead of confirm * move Confirm/ to core * only add style attribute when a height property exists * fix indentation * wip - use new Confirm inside status menu * add Confirm to Storybook * ensure confirm links have proper styling in Storybook and outside popup-menu * fix height transition * disable no-inline-styles * add test selector * remove comment * consolidate Message into Trigger to make Confirm easier to use * use new Trigger API in status menu * remove height transition * fix binding inline style warning * rename confirmMessage to message * update Confirm for Storybook * fix indentation * do not pass in onCancel from outer template because it is static * add jsdoc comments to Trigger * wip - add trigger and confirm to storybook * fix status menu styling * fix styling of confirm stories * use new Confirm on secrets engine list * use bulma speed variable * fix indentation * re-renable eslint no-inline-styles * showConfirm when rendered trigger matches id * fix background color on namespace picker * do not expose onTrigger * Revert "re-renable eslint no-inline-styles" This reverts commit c7b2a9097f177a2876afaaec6020f73b07bad3c7. * rename Confirm Trigger to Message * add tests * update JSDocs * focus trigger after cancelling the confirm message * update Confirm JSDocs * differentiate between ConfirmAction and Confirm * add Message to Storybook * re-enable eslint import/extensions * update confirmButtonText to Revoke token * remove linebreak and extra whitespace * fix typo * add loading to empty button * fix more typos * only show Message contents when showConfirm is true * no need to disable the confirm buttons since they only render in the DOM when showConfirm is true * use Confirm to delete aws roles * use Confirm to delete pki roles * use Confirm to delete ssh roles * add Confirm to entity alias page * fix confirm button text on Revoke token in status menu * ensure you can use tab to revoke a token from status menu * reset the open trigger after the confirm has been confirmed * use Confirm on identity list pages * fix Disable engine confirmation text * use <PopupMenu /> angle brack syntax * use Confirm on policies list page * use Confirm for namespaces * use Confirm for kmip scopes * use Confirm for deleting kmip roles * use Confirm for revoking KMIP credentials * fix Revoke token triggerText
This commit is contained in:
@@ -1,3 +1,75 @@
|
||||
.confirm-wrapper {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
box-shadow: $box-shadow, $box-shadow-middle;
|
||||
}
|
||||
|
||||
.confirm {
|
||||
transition: transform $speed;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.show-confirm {
|
||||
transform: translateX(-100%);
|
||||
transition: transform $speed;
|
||||
}
|
||||
|
||||
.confirm.show-confirm {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.confirm-overlay {
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.confirm,
|
||||
.confirm-overlay {
|
||||
button.link,
|
||||
a {
|
||||
background-color: $white;
|
||||
color: $menu-item-color;
|
||||
|
||||
&:hover {
|
||||
background-color: $menu-item-hover-background-color;
|
||||
color: $menu-item-hover-color;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
background-color: $menu-item-active-background-color;
|
||||
color: $menu-item-active-color;
|
||||
}
|
||||
|
||||
&.is-destroy {
|
||||
color: $red;
|
||||
|
||||
&:hover {
|
||||
background-color: $red;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-action span .button {
|
||||
display: block;
|
||||
margin: 0.25rem auto;
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.confirm-action > span {
|
||||
@include from($tablet) {
|
||||
align-items: center;
|
||||
@@ -22,7 +94,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.popup-menu-content .confirm-action-message {
|
||||
.confirm-action-message {
|
||||
margin: 0;
|
||||
|
||||
.message {
|
||||
@@ -56,6 +128,7 @@
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
width: auto;
|
||||
padding: $spacing-xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
border-radius: $radius;
|
||||
box-shadow: $box-shadow, $box-shadow-high;
|
||||
|
||||
&.ember-basic-dropdown-content {
|
||||
background: $white;
|
||||
}
|
||||
|
||||
@include from($mobile) {
|
||||
width: $drawer-width;
|
||||
}
|
||||
|
||||
@@ -135,6 +135,8 @@
|
||||
}
|
||||
|
||||
.ember-basic-dropdown-content {
|
||||
background-color: transparent;
|
||||
|
||||
&--left.popup-menu {
|
||||
margin: 0px 0 0 -8px;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<Confirm as |c|>
|
||||
<div class="popup-menu-content">
|
||||
<div class="box">
|
||||
<div class="menu-label">
|
||||
@@ -30,27 +31,25 @@
|
||||
</button>
|
||||
</li>
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="button link is-destroy"
|
||||
@confirmTitle={{concat "Revoke " (get auth 'authData.displayName') "?"}}
|
||||
@confirmMessage={{concat "You will not be able to log in again with this token."}}
|
||||
@confirmButtonText="Revoke"
|
||||
@onConfirmAction={{action "revokeToken"}}
|
||||
>
|
||||
Revoke token
|
||||
</ConfirmAction>
|
||||
<c.Message
|
||||
@id={{get auth 'authData.displayName'}}
|
||||
@title={{concat "Revoke " (get auth 'authData.displayName') "?"}}
|
||||
@onConfirm={{action "revokeToken"}}
|
||||
@message="You will not be able to log in again with this token."
|
||||
@triggerText="Revoke token"
|
||||
@confirmButtonText='Revoke'
|
||||
/>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="action text-right">
|
||||
<ConfirmAction
|
||||
@buttonClasses="button link is-destroy"
|
||||
@confirmTitle={{concat "Revoke " (get auth 'authData.displayName') "?"}}
|
||||
@confirmMessage={{concat "You will not be able to log in again with this token."}}
|
||||
@confirmButtonText="Revoke"
|
||||
@onConfirmAction={{action "revokeToken"}}
|
||||
>
|
||||
Revoke token
|
||||
</ConfirmAction>
|
||||
<c.Message
|
||||
@id={{get auth 'authData.displayName'}}
|
||||
@title={{concat "Revoke " (get auth 'authData.displayName') "?"}}
|
||||
@onConfirm={{action "revokeToken"}}
|
||||
@message="You will not be able to log in again with this token."
|
||||
@triggerText="Revoke token"
|
||||
@confirmButtonText='Revoke'
|
||||
/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
@@ -63,3 +62,4 @@
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</Confirm>
|
||||
|
||||
@@ -1,39 +1,37 @@
|
||||
{{#popup-menu name="alias-menu"}}
|
||||
{{#with params.firstObject as |item|}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.aliases.show" (pluralize item.parentType) item.id "details"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canEdit}}
|
||||
<Confirm as |c|>
|
||||
{{#with params.firstObject as |item|}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.aliases.edit" (pluralize item.parentType) item.id}}
|
||||
Edit
|
||||
{{#link-to "vault.cluster.access.identity.aliases.show" (pluralize item.parentType) item.id "details"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action "performTransaction" item}}
|
||||
data-test-item-delete="true"
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
{{/with}}
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.aliases.edit" (pluralize item.parentType) item.id}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@onConfirm={{action "performTransaction" item}} />
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
{{/with}}
|
||||
</Confirm>
|
||||
{{/popup-menu}}
|
||||
|
||||
@@ -1,57 +1,56 @@
|
||||
{{#popup-menu name="role-aws-nav" contentClass="is-wide"}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if item.generatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id data-test-role-aws-link="generate"}}
|
||||
Generate credentials
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if item.generatePath.isPending}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.show" item.id data-test-role-ssh-link="show"}}
|
||||
Details
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id data-test-role-aws-link="generate"}}
|
||||
Generate credentials
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.edit" item.id data-test-role-ssh-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action "delete" item}}
|
||||
data-test-aws-role-delete={{item.id}}
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.show" item.id data-test-role-ssh-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.edit" item.id data-test-role-ssh-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@onConfirm={{action "delete" item}}
|
||||
data-test-aws-role-delete={{item.id}}/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
{{/popup-menu}}
|
||||
|
||||
@@ -1,70 +1,69 @@
|
||||
{{#popup-menu name="role-aws-nav"}}
|
||||
<nav class="menu">
|
||||
{{#if (or item.generatePath.isPending item.signPath.isPending)}}
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{else if (or item.canGenerate item.canSign)}}
|
||||
<ul class="menu-list">
|
||||
{{#if item.canGenerate}}
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
{{#if (or item.generatePath.isPending item.signPath.isPending)}}
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id (query-params action="issue") data-test-role-pki-link="generate-certificate"}}
|
||||
Generate certificate
|
||||
{{/link-to}}
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canSign}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id (query-params action="sign") data-test-role-pki-link="sign-certificate"}}
|
||||
Sign certificate
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
<ul class="menu-list">
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.show" item.id data-test-role-pki-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.edit" item.id data-test-role-pki-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action "delete" item}}
|
||||
data-test-aws-role-delete={{item.id}}
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{else if (or item.canGenerate item.canSign)}}
|
||||
<ul class="menu-list">
|
||||
{{#if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id (query-params action="issue") data-test-role-pki-link="generate-certificate"}}
|
||||
Generate certificate
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canSign}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id (query-params action="sign") data-test-role-pki-link="sign-certificate"}}
|
||||
Sign certificate
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
<ul class="menu-list">
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.show" item.id data-test-role-pki-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.edit" item.id data-test-role-pki-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@onConfirm={{action "delete" item}}
|
||||
data-test-pki-role-delete={{item.id}}/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
{{/popup-menu}}
|
||||
|
||||
@@ -1,94 +1,93 @@
|
||||
{{#popup-menu name="role-ssh-nav"}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if (eq item.keyType 'otp')}}
|
||||
{{#if item.generatePath.isPending}}
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if (eq item.keyType 'otp')}}
|
||||
{{#if item.generatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id data-test-role-ssh-link="generate"}}
|
||||
Generate Credentials
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{else if (eq item.keyType 'ca')}}
|
||||
{{#if item.signPath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.sign" item.id data-test-role-ssh-link="generate"}}
|
||||
Sign Keys
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.canEditZeroAddress}}
|
||||
{{#if item.zeroAddress}}
|
||||
<li class="action">
|
||||
<button type="button" disabled={{get this (concat "loading-" item.id)}} class="link button is-transparent
|
||||
{{if (get this (concat "loading-" item.id)) 'is-loading'}} " {{action "toggleZeroAddress" item backendModel}}>
|
||||
Disable Zero Address
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="action">
|
||||
<button
|
||||
type="button"
|
||||
disabled={{get this (concat "loading-" item.id)}}
|
||||
class="link button is-transparent {{if (get this (concat "loading-" item.id)) 'is-loading'}}"
|
||||
{{action "toggleZeroAddress" item backendModel}}
|
||||
>
|
||||
Enable Zero Address
|
||||
</button>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.credentials" item.id data-test-role-ssh-link="generate"}}
|
||||
Generate Credentials
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{else if (eq item.keyType 'ca')}}
|
||||
{{#if item.signPath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else if item.canGenerate}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.sign" item.id data-test-role-ssh-link="generate"}}
|
||||
Sign Keys
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.canEditZeroAddress}}
|
||||
{{#if item.zeroAddress}}
|
||||
<li class="action">
|
||||
<button type="button" disabled={{get this (concat "loading-" item.id)}} class="link button is-transparent
|
||||
{{if (get this (concat "loading-" item.id)) 'is-loading'}} " {{action "toggleZeroAddress" item backendModel}}>
|
||||
Disable Zero Address
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
<li class="action">
|
||||
<button
|
||||
type="button"
|
||||
disabled={{get this (concat "loading-" item.id)}}
|
||||
class="link button is-transparent {{if (get this (concat "loading-" item.id)) 'is-loading'}}"
|
||||
{{action "toggleZeroAddress" item backendModel}}
|
||||
>
|
||||
Enable Zero Address
|
||||
</button>
|
||||
</li>
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.show" item.id data-test-role-ssh-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.edit" item.id data-test-role-ssh-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@onConfirm={{action "delete" item}}
|
||||
data-test-ssh-role-delete={{item.id}}/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.show" item.id data-test-role-ssh-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.edit" item.id data-test-role-ssh-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action "delete" item}}
|
||||
data-test-ssh-role-delete={{item.id}}
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
{{/popup-menu}}
|
||||
|
||||
@@ -14,88 +14,78 @@
|
||||
<SecretLink
|
||||
@mode={{if item.isFolder "list" "show" }}
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold"
|
||||
><Icon
|
||||
@class="has-text-black has-text-weight-semibold"><Icon
|
||||
@glyph={{if item.isFolder 'folder-outline' 'file-outline' }}
|
||||
@class="has-text-grey-light"
|
||||
/>{{if (eq item.id ' ') '(self)' (or item.keyWithoutParent item.id)}}
|
||||
@class="has-text-grey-light"/>{{if (eq item.id ' ') '(self)' (or item.keyWithoutParent item.id)}}
|
||||
</SecretLink>
|
||||
</div>
|
||||
<div class="column has-text-right">
|
||||
<PopupMenu name="secret-menu">
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if item.isFolder}}
|
||||
<SecretLink
|
||||
@mode="list"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold"
|
||||
>
|
||||
Contents
|
||||
</SecretLink>
|
||||
{{else}}
|
||||
{{#if (or item.versionPath.isLoading item.secretPath.isLoading)}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
<SecretLink
|
||||
@mode="show"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold"
|
||||
>
|
||||
Details
|
||||
</SecretLink>
|
||||
</li>
|
||||
{{#if backendModel.isV2KV}}
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if item.isFolder}}
|
||||
<SecretLink
|
||||
@mode="list"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold">
|
||||
Contents
|
||||
</SecretLink>
|
||||
{{else}}
|
||||
{{#if (or item.versionPath.isLoading item.secretPath.isLoading)}}
|
||||
<li class="action">
|
||||
<SecretLink
|
||||
@mode="versions"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold"
|
||||
>
|
||||
View version history
|
||||
</SecretLink>
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
<SecretLink
|
||||
@mode="show"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold">
|
||||
Details
|
||||
</SecretLink>
|
||||
</li>
|
||||
{{#if backendModel.isV2KV}}
|
||||
<li class="action">
|
||||
<SecretLink
|
||||
@mode="versions"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold">
|
||||
View version history
|
||||
</SecretLink>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
<SecretLink
|
||||
@mode="edit"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold">
|
||||
{{if backendModel.isV2KV
|
||||
"Create new version"
|
||||
"Edit"
|
||||
}}
|
||||
</SecretLink>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@triggerText={{if backendModel.isV2KV "Permanently delete" "Delete"}}
|
||||
@message="This will permanently delete this secret and all its versions."
|
||||
@onConfirm={{action "delete" item "secret"}}/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
<SecretLink
|
||||
@mode="edit"
|
||||
@secret={{item.id}}
|
||||
@class="has-text-black has-text-weight-semibold"
|
||||
>
|
||||
{{if backendModel.isV2KV
|
||||
"Create new version"
|
||||
"Edit"
|
||||
}}
|
||||
</SecretLink>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@confirmMessage="This will permanently delete this secret and all its versions."
|
||||
@onConfirmAction={{action "delete" item "secret"}}
|
||||
data-test-v2-kv-delete={{item.id}}
|
||||
>
|
||||
{{if backendModel.isV2KV
|
||||
"Permanently delete"
|
||||
"Delete"
|
||||
}}
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
</PopupMenu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,65 +31,63 @@
|
||||
</div>
|
||||
<div class="column has-text-right">
|
||||
{{#popup-menu name="identity-item" onOpen=(action "reloadRecord" item)}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.show" item.id "details"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{#if (or item.isReloading item.updatePath.isPending item.aliasPath.isPending)}}
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
{{#link-to "vault.cluster.access.identity.show" item.id "details"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canAddAlias}}
|
||||
{{#if (or item.isReloading item.updatePath.isPending item.aliasPath.isPending)}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.aliases.add" (pluralize identityType) item.id}}
|
||||
Create alias
|
||||
{{/link-to}}
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canAddAlias}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.aliases.add" (pluralize identityType) item.id}}
|
||||
Create alias
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.edit" item.id}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li class="action">
|
||||
{{#if item.disabled}}
|
||||
<button type="button" {{action "toggleDisabled" item}} class="link">
|
||||
Enable
|
||||
</button>
|
||||
{{else if (eq identityType 'entity')}}
|
||||
<c.Message
|
||||
@id="{{item.id}}-disable"
|
||||
@triggerText="Disable"
|
||||
@message="Associated tokens will not be revoked, but cannot be used"
|
||||
@title="Disable this?"
|
||||
@confirmButtonText="Disable"
|
||||
@onConfirm={{action "toggleDisabled" item}}
|
||||
data-test-engine-disable="true"/>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@onConfirm={{action "delete" item}}
|
||||
data-test-item-delete="true"/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.access.identity.edit" item.id}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li class="action">
|
||||
{{#if item.disabled}}
|
||||
<button type="button" {{action "toggleDisabled" item}} class="link">
|
||||
Enable
|
||||
</button>
|
||||
{{else if (eq identityType 'entity')}}
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@confirmTitle="Disable this?"
|
||||
@confirmMessage="Associated tokens will not be revoked, but cannot be used"
|
||||
@confirmButtonText="Disable"
|
||||
@onConfirmAction={{action "toggleDisabled" item}}
|
||||
>
|
||||
Disable
|
||||
</ConfirmAction>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action "delete" item}}
|
||||
data-test-item-delete="true"
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
{{/popup-menu}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<Item.content>
|
||||
{{list.item.id}}
|
||||
</Item.content>
|
||||
<Item.menu>
|
||||
<Item.menu as |m|>
|
||||
{{#with (concat currentNamespace (if currentNamespace "/") list.item.id) as |targetNamespace|}}
|
||||
{{#if (contains targetNamespace accessibleNamespaces)}}
|
||||
<li class="action">
|
||||
@@ -45,11 +45,11 @@
|
||||
{{/if}}
|
||||
{{/with}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
<m.Message
|
||||
@id={{list.item.id}}
|
||||
@confirmButtonText="Remove"
|
||||
@confirmMessage="Any engines or mounts in this namespace will also be removed."
|
||||
@onConfirmAction={{action
|
||||
@message="Any engines or mounts in this namespace will also be removed."
|
||||
@onConfirm={{action
|
||||
(perform
|
||||
Item.callMethod
|
||||
"destroyRecord"
|
||||
@@ -58,10 +58,7 @@
|
||||
"There was an error deleting this namespace: "
|
||||
(action "refreshNamespaceList")
|
||||
)
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
}} />
|
||||
</li>
|
||||
</Item.menu>
|
||||
</ListItem>
|
||||
|
||||
@@ -88,51 +88,50 @@
|
||||
{{/link-to}}
|
||||
</div>
|
||||
<div class="column has-text-right">
|
||||
{{#popup-menu name="policy-nav"}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<PopupMenu name="policy-nav">
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.policy.show" policyType item.id data-test-policy-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.policy.edit" policyType item.id data-test-policy-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{else}}
|
||||
{{#if item.canRead}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.policy.show" policyType item.id data-test-policy-link="show"}}
|
||||
Details
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canEdit}}
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.policy.edit" policyType item.id data-test-policy-link="edit"}}
|
||||
Edit
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@confirmMessage="This will permanently delete this policy and may affect access to some data"
|
||||
@onConfirm={{action "deletePolicy" item}}
|
||||
data-test-policy-delete={{item.id}}/>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if item.canDelete}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@confirmMessage="This will permanently delete this policy and may affect access to some data"
|
||||
@onConfirmAction={{action "deletePolicy" item}}
|
||||
data-test-policy-delete={{item.id}}
|
||||
>
|
||||
Delete
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
{{/popup-menu}}
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
</PopupMenu>
|
||||
</div>
|
||||
</div>
|
||||
{{/linked-block}}
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<div class="level-right is-flex is-paddingless is-marginless">
|
||||
<div class="level-item">
|
||||
{{#popup-menu name="engine-menu"}}
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
@@ -78,25 +79,27 @@
|
||||
</li>
|
||||
{{#unless (eq backend.type "cubbyhole")}}
|
||||
<li class="action">
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@confirmTitle="Disable engine?"
|
||||
@confirmMessage="Any data in this engine will be permanently deleted."
|
||||
<c.Message
|
||||
@id={{backend.id}}
|
||||
@triggerText="Disable"
|
||||
@message="Any data in this engine will be permanently deleted."
|
||||
@title="Disable engine?"
|
||||
@confirmButtonText="Disable"
|
||||
@onConfirmAction={{perform disableEngine backend}}
|
||||
@onConfirm={{perform disableEngine backend}}
|
||||
data-test-engine-disable="true"
|
||||
>
|
||||
Disable
|
||||
</ConfirmAction>
|
||||
/>
|
||||
</li>
|
||||
{{/unless}}
|
||||
{{#if item.updatePath.isPending}}
|
||||
<li class="action">
|
||||
<button disabled type="button" class="link button is-loading is-transparent"></button>
|
||||
<button disabled type="button" class="link button is-loading is-transparent">
|
||||
loading
|
||||
</button>
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
{{/popup-menu}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,29 +134,30 @@
|
||||
</div>
|
||||
<div class="level-right is-flex is-paddingless is-marginless">
|
||||
<div class="level-item">
|
||||
{{#popup-menu name="engine-menu"}}
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.configuration" backend.id data-test-engine-config}}
|
||||
View configuration
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@confirmTitle="Disable engine?"
|
||||
@confirmMessage="Any data in this engine will be permanently deleted."
|
||||
@confirmButtonText="Disable"
|
||||
@onConfirmAction={{perform disableEngine backend}}
|
||||
data-test-engine-disable="true"
|
||||
>
|
||||
Disable
|
||||
</ConfirmAction>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{/popup-menu}}
|
||||
<PopupMenu name="engine-menu">
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
<li class="action">
|
||||
{{#link-to "vault.cluster.secrets.backend.configuration" backend.id data-test-engine-config}}
|
||||
View configuration
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
<c.Message
|
||||
@id={{backend.id}}
|
||||
@triggerText="Disable"
|
||||
@message="Any data in this engine will be permanently deleted."
|
||||
@title="Disable engine?"
|
||||
@confirmButtonText="Disable"
|
||||
@onConfirm={{perform disableEngine backend}}
|
||||
data-test-engine-disable="true"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
</PopupMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
<%= importMD %>
|
||||
|
||||
@@ -3,7 +3,7 @@ import layout from '../templates/components/confirm-action';
|
||||
|
||||
/**
|
||||
* @module ConfirmAction
|
||||
* `ConfirmAction` is a button followed by a confirmation message and button used to prevent users from performing actions they do not intend to.
|
||||
* `ConfirmAction` is a button followed by a pop up confirmation message and button used to prevent users from performing actions they do not intend to.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
|
||||
70
ui/lib/core/addon/components/confirm.js
Normal file
70
ui/lib/core/addon/components/confirm.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import { htmlSafe } from '@ember/template';
|
||||
import layout from '../templates/components/confirm';
|
||||
import { next } from '@ember/runloop';
|
||||
|
||||
/**
|
||||
* @module Confirm
|
||||
* `Confirm` components prevent users from performing actions they do not intend to by showing a confirmation message as an overlay. This is a contextual component that should always be rendered with a `Message` which triggers the message.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <div class="box">
|
||||
* <Confirm as |c|>
|
||||
* <c.Message
|
||||
* @id={{item.id}}
|
||||
* @triggerText="Delete"
|
||||
* @message="This will permanently delete this secret and all its versions."
|
||||
* @onConfirm={{action "delete" item "secret"}}
|
||||
* />
|
||||
* </Confirm>
|
||||
* </div>
|
||||
* ```
|
||||
*/
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
openTrigger: null,
|
||||
height: 0,
|
||||
focusTrigger: null,
|
||||
style: computed('height', function() {
|
||||
return htmlSafe(`height: ${this.height}px`);
|
||||
}),
|
||||
wormholeReference: null,
|
||||
wormholeId: computed(function() {
|
||||
return `confirm-${this.elementId}`;
|
||||
}),
|
||||
didInsertElement() {
|
||||
this.set('wormholeReference', this.element.querySelector(`#${this.wormholeId}`));
|
||||
},
|
||||
didRender() {
|
||||
this.updateHeight();
|
||||
},
|
||||
updateHeight: function() {
|
||||
let height;
|
||||
height = this.openTrigger
|
||||
? this.element.querySelector('.confirm-overlay').clientHeight
|
||||
: this.element.querySelector('.confirm').clientHeight;
|
||||
this.set('height', height);
|
||||
},
|
||||
actions: {
|
||||
onTrigger: function(itemId, e) {
|
||||
this.set('openTrigger', itemId);
|
||||
|
||||
// store a reference to the trigger so we can focus the element
|
||||
// after clicking cancel
|
||||
this.set('focusTrigger', e.target);
|
||||
this.updateHeight();
|
||||
},
|
||||
onCancel: function() {
|
||||
this.set('openTrigger', '');
|
||||
this.updateHeight();
|
||||
|
||||
next(() => {
|
||||
this.focusTrigger.focus();
|
||||
this.set('focusTrigger', null);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
54
ui/lib/core/addon/components/confirm/message.js
Normal file
54
ui/lib/core/addon/components/confirm/message.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import layout from '../../templates/components/confirm/message';
|
||||
|
||||
/**
|
||||
* @module Message
|
||||
* `Message` components trigger and display a confirmation message. They should only be used within a `Confirm` component.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* <div class="box">
|
||||
* <Confirm as |c|>
|
||||
* <c.Message
|
||||
* @id={{item.id}}
|
||||
* @triggerText="Delete"
|
||||
* @message="This will permanently delete this secret and all its versions."
|
||||
* @onConfirm={{action "delete" item "secret"}}
|
||||
* />
|
||||
* </Confirm>
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* @property id=null {ID} - A unique identifier used to bind a trigger to a confirmation message.
|
||||
* @property onConfirm=null {Func} - The action to take when the user clicks the confirm button.
|
||||
* @property [triggerText='Delete'] {String} - The text on the trigger button.
|
||||
* @property [title='Delete this?'] {String} - The header text to display in the confirmation message.
|
||||
* @property [message='You will not be able to recover it later.'] {String} - The message to display above the confirm and cancel buttons.
|
||||
* @property [confirmButtonText='Delete'] {String} - The text to display on the confirm button.
|
||||
* @property [cancelButtonText='Cancel'] {String} - The text to display on the cancel button.
|
||||
*/
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
tagName: '',
|
||||
renderedTrigger: null,
|
||||
id: null,
|
||||
onCancel() {},
|
||||
onConfirm() {},
|
||||
resetTrigger() {},
|
||||
title: 'Delete this?',
|
||||
message: 'You will not be able to recover it later.',
|
||||
triggerText: 'Delete',
|
||||
confirmButtonText: 'Delete',
|
||||
cancelButtonText: 'Cancel',
|
||||
showConfirm: computed('renderedTrigger', function() {
|
||||
return this.renderedTrigger === this.id;
|
||||
}),
|
||||
actions: {
|
||||
onConfirm() {
|
||||
this.onConfirm();
|
||||
this.resetTrigger();
|
||||
},
|
||||
},
|
||||
});
|
||||
17
ui/lib/core/addon/templates/components/confirm.hbs
Normal file
17
ui/lib/core/addon/templates/components/confirm.hbs
Normal file
@@ -0,0 +1,17 @@
|
||||
{{! template-lint-disable no-inline-styles}}
|
||||
|
||||
<div class="confirm-wrapper" style={{style}}>
|
||||
<div class="confirm {{if openTrigger "show-confirm"}}" ...attributes>
|
||||
{{yield (hash
|
||||
Message=(component "confirm/message"
|
||||
renderedTrigger=(readonly this.openTrigger)
|
||||
wormholeReference=this.wormholeReference
|
||||
onCancel=(action 'onCancel')
|
||||
onTrigger=(action 'onTrigger')
|
||||
resetTrigger=(action (mut this.openTrigger) "")
|
||||
))
|
||||
}}
|
||||
</div>
|
||||
<div id={{this.wormholeId}} class="confirm-overlay {{if openTrigger "show-confirm"}}">
|
||||
</div>
|
||||
</div>
|
||||
40
ui/lib/core/addon/templates/components/confirm/message.hbs
Normal file
40
ui/lib/core/addon/templates/components/confirm/message.hbs
Normal file
@@ -0,0 +1,40 @@
|
||||
{{#if showConfirm}}
|
||||
{{#maybe-in-element wormholeReference false}}
|
||||
<div class="confirm-action-message">
|
||||
<div class="message is-highlight">
|
||||
<div class="message-title">
|
||||
<Icon @glyph="alert-triangle" />
|
||||
{{title}}
|
||||
</div>
|
||||
<p>
|
||||
{{message}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="confirm-action-options">
|
||||
<button
|
||||
type="button"
|
||||
class="link is-destroy"
|
||||
data-test-confirm-button="true"
|
||||
onclick={{action "onConfirm"}}>
|
||||
{{confirmButtonText}}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="link"
|
||||
data-test-confirm-cancel-button="true"
|
||||
{{action this.onCancel}}>
|
||||
{{cancelButtonText}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{/maybe-in-element}}
|
||||
{{/if}}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="link is-destroy"
|
||||
disabled={{showConfirm}}
|
||||
onclick={{action this.onTrigger id}}
|
||||
data-test-confirm-action-trigger={{id}}>
|
||||
{{triggerText}}
|
||||
</button>
|
||||
@@ -1,10 +1,12 @@
|
||||
{{#if hasMenu}}
|
||||
<PopupMenu>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{yield item}}
|
||||
</ul>
|
||||
</nav>
|
||||
<Confirm as |c|>
|
||||
<nav class="menu">
|
||||
<ul class="menu-list">
|
||||
{{yield (hash Message=c.Message)}}
|
||||
</ul>
|
||||
</nav>
|
||||
</Confirm>
|
||||
</PopupMenu>
|
||||
{{else}}
|
||||
{{yield item}}
|
||||
|
||||
1
ui/lib/core/app/components/confirm.js
Normal file
1
ui/lib/core/app/components/confirm.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from 'core/components/confirm';
|
||||
1
ui/lib/core/app/components/confirm/message.js
Normal file
1
ui/lib/core/app/components/confirm/message.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from 'core/components/confirm/message';
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--THIS FILE IS AUTO GENERATED. This file is generated from JSDoc comments in app/components/confirm-action.js. To make changes, first edit that file and run "yarn gen-story-md confirm-action" to re-generate the content.-->
|
||||
|
||||
## ConfirmAction
|
||||
`ConfirmAction` is a button followed by a confirmation message and button used to prevent users from performing actions they do not intend to.
|
||||
`ConfirmAction` is a button followed by a pop up confirmation message and button used to prevent users from performing actions they do not intend to.
|
||||
|
||||
**Properties**
|
||||
|
||||
|
||||
28
ui/lib/core/stories/confirm.md
Normal file
28
ui/lib/core/stories/confirm.md
Normal file
@@ -0,0 +1,28 @@
|
||||
<!--THIS FILE IS AUTO GENERATED. This file is generated from JSDoc comments in lib/core/addon/components/confirm.js. To make changes, first edit that file and run "yarn gen-story-md confirm" to re-generate the content.-->
|
||||
|
||||
## Confirm
|
||||
`Confirm` components prevent users from performing actions they do not intend to by showing a confirmation message as an overlay. This is a contextual component that should always be rendered with a `Message` which triggers the message.
|
||||
|
||||
See the `Message` component for a description of properties.
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
<div class="box">
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@triggerText="Delete"
|
||||
@message="This will permanently delete this secret and all its versions."
|
||||
@onConfirm={{action "delete" item "secret"}}
|
||||
/>
|
||||
</Confirm>
|
||||
</div>
|
||||
```
|
||||
|
||||
**See**
|
||||
|
||||
- [Uses of Confirm](https://github.com/hashicorp/vault/search?l=Handlebars&q=Confirm+OR+confirm)
|
||||
- [Confirm Source Code](https://github.com/hashicorp/vault/blob/master/ui/lib/core/addon/components/confirm.js)
|
||||
|
||||
---
|
||||
47
ui/lib/core/stories/confirm.stories.js
Normal file
47
ui/lib/core/stories/confirm.stories.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './confirm.md';
|
||||
import { withKnobs, text } from '@storybook/addon-knobs';
|
||||
|
||||
storiesOf('Confirm/Confirm', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(
|
||||
withKnobs({
|
||||
escapeHTML: false,
|
||||
})
|
||||
)
|
||||
.add(
|
||||
`Confirm`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Confirm</h5>
|
||||
<div class="popup-menu-content">
|
||||
<div class="box">
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{id}}
|
||||
@title={{title}}
|
||||
@triggerText={{triggerText}}
|
||||
@message={{message}}
|
||||
@confirmButtonText={{confirmButtonText}}
|
||||
@cancelButtonText={{cancelButtonText}}
|
||||
@onConfirm={{onConfirm}}
|
||||
/>
|
||||
</Confirm>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
context: {
|
||||
id: 'foo',
|
||||
onConfirm: () => {
|
||||
alert('Confirmed!');
|
||||
},
|
||||
title: text('title', 'Delete this?'),
|
||||
message: text('message', 'You will not be able to recover it later.'),
|
||||
confirmButtonText: text('confirmButtonText', 'Delete'),
|
||||
cancelButtonText: text('cancelButtonText', 'Cancel'),
|
||||
triggerText: text('triggerText', 'Delete'),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
||||
39
ui/lib/core/stories/message.md
Normal file
39
ui/lib/core/stories/message.md
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--THIS FILE IS AUTO GENERATED. This file is generated from JSDoc comments in lib/core/addon/components/confirm.js. To make changes, first edit that file and run "yarn gen-story-md confirm" to re-generate the content.-->
|
||||
|
||||
## Message
|
||||
`Message` components trigger and display a confirmation message. They should only be used within a `Confirm` component.
|
||||
|
||||
**Properties**
|
||||
|
||||
| Param | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | <code>ID</code> | <code></code> | A unique identifier used to bind a trigger to a confirmation message. |
|
||||
| onConfirm | <code>Func</code> | <code></code> | The action to take when the user clicks the confirm button. |
|
||||
| [triggerText] | <code>String</code> |<code>'Delete'</code> | The text on the trigger button. |
|
||||
| [title] | <code>String</code> | <code>'Delete this?'</code> | The header text to display in the confirmation message. |
|
||||
| [message] | <code>String</code> | <code>'You will not be able to recover it later.'</code> | The message to display above the confirm and cancel buttons. |
|
||||
| [confirmButtonText] | <code>String</code> | <code>'Delete'</code> | The text to display on the confirm button. |
|
||||
| [cancelButtonText] | <code>String</code> | <code>'Cancel'</code> | The text to display on the cancel button. |
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
```js
|
||||
<div class="box">
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{item.id}}
|
||||
@triggerText="Delete"
|
||||
@message="This will permanently delete this secret and all its versions."
|
||||
@onConfirm={{action "delete" item "secret"}}
|
||||
/>
|
||||
</Confirm>
|
||||
</div>
|
||||
```
|
||||
|
||||
**See**
|
||||
|
||||
- [Uses of Confirm](https://github.com/hashicorp/vault/search?l=Handlebars&q=Confirm+OR+confirm)
|
||||
- [Confirm Source Code](https://github.com/hashicorp/vault/blob/master/ui/lib/core/addon/components/confirm.js)
|
||||
|
||||
---
|
||||
19
ui/lib/core/stories/message.stories.js
Normal file
19
ui/lib/core/stories/message.stories.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './message.md';
|
||||
|
||||
storiesOf('Confirm/Message/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.add(
|
||||
`Message`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Message</h5>
|
||||
<p>
|
||||
<code>Message</code> components should never render on their own. See the <code>Confirm</code> component for an example of what a <code>Message</code> looks like.
|
||||
</p>
|
||||
`,
|
||||
context: {},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
||||
@@ -54,7 +54,7 @@
|
||||
<Item.content>
|
||||
<Icon @glyph="pki" class="has-text-grey-light" @size="l" />{{list.item.id}}
|
||||
</Item.content>
|
||||
<Item.menu>
|
||||
<Item.menu as |m|>
|
||||
<li class="action">
|
||||
{{#link-to "credentials.show" this.scope this.role list.item.id class="is-block"}}
|
||||
View credentials
|
||||
@@ -62,9 +62,13 @@
|
||||
</li>
|
||||
{{#if list.item.deletePath.canDelete}}
|
||||
<MenuLoader @loadingParam={{list.item.deletePath.isPending}}>
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action
|
||||
<m.Message
|
||||
@id={{list.item.id}}
|
||||
@triggerText="Revoke credentials"
|
||||
@title="Revoke this?"
|
||||
@message="Any client using these credentials will no longer be able to."
|
||||
@confirmButtonText="Revoke"
|
||||
@onConfirm={{action
|
||||
(perform
|
||||
Item.callMethod
|
||||
"destroyRecord"
|
||||
@@ -74,13 +78,7 @@
|
||||
(action "refresh")
|
||||
)
|
||||
}}
|
||||
@confirmTitle="Revoke this?"
|
||||
@confirmMessage="Any client using these credentials will no longer be able to."
|
||||
@cancelButtonText="Cancel"
|
||||
@confirmButtonText="Revoke"
|
||||
>
|
||||
Revoke credentials
|
||||
</ConfirmAction>
|
||||
/>
|
||||
</MenuLoader>
|
||||
{{/if}}
|
||||
</Item.menu>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<Item.content>
|
||||
<Icon @glyph="user-plain" class="has-text-grey-light" @size="l" />{{list.item.id}}
|
||||
</Item.content>
|
||||
<Item.menu>
|
||||
<Item.menu as |m|>
|
||||
<li class="action">
|
||||
{{#link-to "credentials" this.scope list.item.id class="is-block"}}
|
||||
View credentials
|
||||
@@ -84,9 +84,11 @@
|
||||
{{/if}}
|
||||
{{#if list.item.updatePath.canDelete}}
|
||||
<MenuLoader @loadingParam={{list.item.updatePath.isPending}}>
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action
|
||||
<m.Message
|
||||
@id={{list.item.id}}
|
||||
@triggerText='Delete role'
|
||||
@message={{concat "Are you sure you want to delete " list.item.id "?"}}
|
||||
@onConfirm={{action
|
||||
(perform
|
||||
Item.callMethod
|
||||
"destroyRecord"
|
||||
@@ -96,12 +98,8 @@
|
||||
(action "refresh")
|
||||
)
|
||||
}}
|
||||
@confirmMessage={{concat "Are you sure you want to delete " list.item.id "?"}}
|
||||
@cancelButtonText="Cancel"
|
||||
data-test-scope-delete="true"
|
||||
>
|
||||
Delete role
|
||||
</ConfirmAction>
|
||||
/>
|
||||
</MenuLoader>
|
||||
{{/if}}
|
||||
</Item.menu>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<Item.content>
|
||||
<Icon @glyph="folder-outline" class="has-text-grey-light" @size="l" />{{list.item.id}}
|
||||
</Item.content>
|
||||
<Item.menu>
|
||||
<Item.menu as |m|>
|
||||
<li class="action">
|
||||
{{#link-to "scope" list.item.id class="is-block"}}
|
||||
View scope
|
||||
@@ -62,9 +62,13 @@
|
||||
</li>
|
||||
{{#if list.item.updatePath.canDelete}}
|
||||
<MenuLoader @loadingParam={{list.item.updatePath.isPending}}>
|
||||
<ConfirmAction
|
||||
@buttonClasses="link is-destroy"
|
||||
@onConfirmAction={{action
|
||||
<m.Message
|
||||
@id={{list.item.id}}
|
||||
@triggerText='Delete scope'
|
||||
@title={{concat "Delete scope " list.item.id "?"}}
|
||||
@message="This will permanently delete this scope and all roles and credentials contained within"
|
||||
@cancelButtonText="Cancel"
|
||||
@onConfirm={{action
|
||||
(perform
|
||||
Item.callMethod
|
||||
"destroyRecord"
|
||||
@@ -74,13 +78,7 @@
|
||||
(action "refresh")
|
||||
)
|
||||
}}
|
||||
@confirmTitle={{concat "Delete scope " list.item.id "?"}}
|
||||
@confirmMessage="This will permanently delete this scope and all roles and credentials contained within"
|
||||
@cancelButtonText="Cancel"
|
||||
data-test-scope-delete="true"
|
||||
>
|
||||
Delete scope
|
||||
</ConfirmAction>
|
||||
data-test-scope-delete="true" />
|
||||
</MenuLoader>
|
||||
{{/if}}
|
||||
</Item.menu>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './alert-popup.md';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './auth-form.md';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, object } from '@storybook/addon-knobs';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, object } from '@storybook/addon-knobs';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable import/extensions */
|
||||
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, object } from '@storybook/addon-knobs';
|
||||
|
||||
102
ui/tests/integration/components/confirm-test.js
Normal file
102
ui/tests/integration/components/confirm-test.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, click } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import sinon from 'sinon';
|
||||
|
||||
module('Integration | Component | Confirm', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function() {
|
||||
this.set('id', 'foo');
|
||||
this.set('title', 'Are you sure?');
|
||||
this.set('message', 'You will not be able to recover this item later.');
|
||||
this.set('triggerText', 'Click me!');
|
||||
this.set('onConfirm', sinon.spy());
|
||||
});
|
||||
|
||||
test('it renders', async function(assert) {
|
||||
await render(hbs`
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{id}}
|
||||
@title={{title}}
|
||||
@triggerText={{triggerText}}
|
||||
@message={{message}}
|
||||
@onConfirm={{onConfirm}}
|
||||
/>
|
||||
</Confirm>
|
||||
`);
|
||||
|
||||
assert.dom('.confirm-wrapper').exists();
|
||||
assert.dom('.confirm').containsText(this.triggerText);
|
||||
});
|
||||
|
||||
test('does not show the confirmation message until it is triggered', async function(assert) {
|
||||
await render(hbs`
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{id}}
|
||||
@title={{title}}
|
||||
@triggerText={{triggerText}}
|
||||
@message={{message}}
|
||||
@onConfirm={{onConfirm}}
|
||||
/>
|
||||
</Confirm>
|
||||
`);
|
||||
assert.dom('.confirm-overlay').doesNotContainText(this.message);
|
||||
|
||||
await click('[data-test-confirm-action-trigger]');
|
||||
|
||||
assert.dom('.confirm-overlay').containsText(this.title);
|
||||
assert.dom('.confirm-overlay').containsText(this.message);
|
||||
});
|
||||
|
||||
test('it calls onConfirm when the confirm button is clicked', async function(assert) {
|
||||
await render(hbs`
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{id}}
|
||||
@title={{title}}
|
||||
@triggerText={{triggerText}}
|
||||
@message={{message}}
|
||||
@onConfirm={{onConfirm}}
|
||||
/>
|
||||
</Confirm>
|
||||
`);
|
||||
await click('[data-test-confirm-action-trigger]');
|
||||
await click('[data-test-confirm-button=true]');
|
||||
|
||||
assert.ok(this.onConfirm.calledOnce);
|
||||
});
|
||||
|
||||
test('it shows only the active triggers message', async function(assert) {
|
||||
await render(hbs`
|
||||
<Confirm as |c|>
|
||||
<c.Message
|
||||
@id={{id}}
|
||||
@title={{title}}
|
||||
@triggerText={{triggerText}}
|
||||
@message={{message}}
|
||||
@onConfirm={{onConfirm}}
|
||||
/>
|
||||
<c.Message
|
||||
@id='bar'
|
||||
@title='Wow'
|
||||
@message='Bazinga!'
|
||||
@onConfirm={{onConfirm}}
|
||||
/>
|
||||
</Confirm>
|
||||
`);
|
||||
|
||||
await click(`[data-test-confirm-action-trigger=${this.id}]`);
|
||||
assert.dom('.confirm-overlay').containsText(this.title);
|
||||
assert.dom('.confirm-overlay').containsText(this.message);
|
||||
|
||||
await click('[data-test-confirm-cancel-button]');
|
||||
|
||||
await click("[data-test-confirm-action-trigger='bar']");
|
||||
assert.dom('.confirm-overlay').containsText('Wow');
|
||||
assert.dom('.confirm-overlay').containsText('Bazinga!');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user