Truncate Secret Engine Description Text (#11995)

Co-authored-by: hashishaw <cshaw@hashicorp.com>
This commit is contained in:
claire bontempo 2021-07-08 08:21:10 -07:00 committed by GitHub
parent a4bb9baf48
commit 72e3d29abc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 613 additions and 132 deletions

3
changelog/11995.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: Show description on secret engine list
```

View File

@ -0,0 +1,21 @@
.linkable-item {
display: grid;
grid-template-columns: minmax(0, 1fr) 50px 35px;
gap: 1em 1em;
}
.linkable-item-menu {
box-sizing: border-box;
grid-column: 3;
grid-row: 1;
align-self: center;
}
.overflow-ellipsis {
box-sizing: border-box;
&.is-closed {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

View File

@ -0,0 +1,18 @@
.linkable-item-seemore {
grid-column: 2;
grid-row: 1;
align-self: baseline;
}
.overflow-ellipsis {
box-sizing: border-box;
&.is-closed {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.has-font-weight-normal {
font-weight: $font-weight-normal;
}

View File

@ -65,6 +65,7 @@
@import './components/kmip-role-edit';
@import './components/known-secondaries-card.scss';
@import './components/license-banners';
@import './components/linkable-item';
@import './components/linked-block';
@import './components/list-item-row';
@import './components/list-pagination';
@ -81,6 +82,7 @@
@import './components/radio-card';
@import './components/radial-progress';
@import './components/raft-join';
@import './components/read-more';
@import './components/regex-validator';
@import './components/replication-dashboard';
@import './components/replication-doc-link';

View File

@ -11,7 +11,7 @@
<ToolbarLink
@type="add"
@params={{array 'vault.cluster.settings.mount-secret-backend'}}
>
>
Enable new engine
</ToolbarLink>
</ToolbarActions>
@ -24,138 +24,94 @@
"vault.cluster.secrets.backend.overview"
"vault.cluster.secrets.backend.list-root"
)) as |backendLink|}}
{{#linked-block
backendLink
backend.id
class="list-item-row"
data-test-secret-backend-row=backend.id
}}
<div class="level is-mobile">
<div class="level-left">
<div>
<ToolTip @horizontalPosition="left" as |T|>
<T.trigger>
<Icon
@glyph={{or (if (eq backend.engineType "kmip") "secrets" backend.engineType) "secrets"}}
@size="l"
class="has-text-grey-light"
/>
</T.trigger>
<T.content @class="tool-tip">
<div class="box">
{{backend.engineType}}
</div>
</T.content>
</ToolTip>
<LinkTo @route={{backendLink}} @model={{backend.id}} class="has-text-black has-text-weight-semibold" data-test-secret-path={{true}}>
{{backend.path}}
</LinkTo>
<br />
<code class="has-text-grey is-size-8">
{{#if (eq backend.options.version 2)}}
v2
{{/if}}
</code>
<code class="has-text-grey is-size-8">
{{backend.accessor}}
</code>
</div>
</div>
<div class="level-right is-flex is-paddingless is-marginless">
<div class="level-item">
<PopupMenu @name="engine-menu">
<Confirm as |c|>
<nav class="menu">
<ul class="menu-list">
<li class="action">
<LinkTo @route="vault.cluster.secrets.backend.configuration" @model={{backend.id}}>
View configuration
</LinkTo>
</li>
{{#unless (eq backend.type "cubbyhole")}}
<li class="action">
<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>
{{/unless}}
{{#if item.updatePath.isPending}}
<li class="action">
<button disabled type="button" class="link button is-loading is-transparent">
loading
</button>
</li>
{{/if}}
</ul>
</nav>
</Confirm>
</PopupMenu>
</div>
</div>
</div>
{{/linked-block}}
<LinkableItem
data-test-secret-backend-row={{backend.id}}
@link={{hash route=backendLink model=backend.id}}
as |Li|>
<Li.content
@accessor={{if (eq backend.options.version 2) (concat "v2 " backend.accessor) backend.accessor}}
@description={{backend.description}}
@glyphText={{backend.engineType}}
@glyph={{or (if (eq backend.engineType "kmip") "secrets" backend.engineType) "secrets"}}
@link={{hash route=backendLink model=backend.id}}
@title={{backend.path}}
/>
<Li.menu>
<PopupMenu @name="engine-menu">
<Confirm as |c|>
<nav class="menu">
<ul class="menu-list">
<li class="action">
<LinkTo @route="vault.cluster.secrets.backend.configuration" @model={{backend.id}}>
View configuration
</LinkTo>
</li>
{{#unless (eq backend.type "cubbyhole")}}
<li class="action">
<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>
{{/unless}}
{{#if item.updatePath.isPending}}
<li class="action">
<button disabled type="button" class="link button is-loading is-transparent">
loading
</button>
</li>
{{/if}}
</ul>
</nav>
</Confirm>
</PopupMenu>
</Li.menu>
</LinkableItem>
{{/let}}
{{/each}}
{{#each unsupportedBackends as |backend|}}
<div class="list-item-row" data-test-secret-backend-row={{backend.id}}>
<div class="level is-mobile">
<div class="level-left">
<div>
<div data-test-secret-path class="has-text-weight-semibold has-text-grey">
<ToolTip @horizontalPosition="left" as |T|>
<T.trigger>
<Icon
@glyph={{or backend.engineType "secrets"}}
class="has-text-grey-light"
<LinkableItem
data-test-secret-backend-row={{backend.id}}
@disabled={{true}}
as |Li|>
<Li.content
@accessor={{if (eq backend.options.version 2) (concat "v2 " backend.accessor) backend.accessor}}
@description={{backend.description}}
@glyphText={{backend.engineType}}
@glyph={{or (if (eq backend.engineType "kmip") "secrets" backend.engineType) "secrets"}}
@title={{backend.path}}
/>
<Li.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"
/>
</T.trigger>
<T.content @class="tool-tip">
<div class="box">
{{backend.engineType}}
</div>
</T.content>
</ToolTip>
{{backend.path}}
</div>
<code class="has-text-grey is-size-8">
{{backend.accessor}}
</code>
</div>
</div>
<div class="level-right is-flex is-paddingless is-marginless">
<div class="level-item">
<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>
</div>
</li>
</ul>
</nav>
</Confirm>
</PopupMenu>
</Li.menu>
</LinkableItem>
{{/each}}

View File

@ -0,0 +1,22 @@
/**
* @module LinkableItem
* LinkableItem components have two contextual components, a Content component used to show information on the left with a Menu component on the right, all aligned vertically centered. If passed a link, the block will be clickable.
*
* @example
* ```js
* <LinkableItem @link={{hash route='vault.backends' model='my-backend-path'}} data-test-row="my-backend-path">
* // Use <LinkableItem.content> and <LinkableItem.menu> here
* </LinkableItem>
* ```
*
* @param {object} [link=null] - Link should have route and model
* @param {boolean} [disabled=false] - If no link then should be given a disabled attribute equal to true
*/
import Component from '@glimmer/component';
import layout from '../templates/components/linkable-item';
import { setComponentTemplate } from '@ember/component';
class LinkableItemComponent extends Component {}
export default setComponentTemplate(layout, LinkableItemComponent);

View File

@ -0,0 +1,30 @@
/**
* @module Content
* Content components are contextual components of LinkableItem, used to display content on the left side of a LinkableItem component.
*
* @example
* ```js
* <LinkableItem as |Li|>
* <Li.content
* @accessor="cubbyhole_e21f8ee6"
* @description="per-token private secret storage"
* @glyphText="tooltip text"
* @glyph=glyph
* @title="title"
* />
* </LinkableItem>
* ```
* @param {string} accessor=null - formatted as HTML <code> tag
* @param {string} description=null - will truncate if wider than parent div
* @param {string} glyphText=null - tooltip for glyph
* @param {string} glyph=null - will display as icon beside the title
* @param {string} titl=null - if @link object is passed in then title will link to @link.route
*/
import Component from '@glimmer/component';
import layout from '../../templates/components/linkable-item/content';
import { setComponentTemplate } from '@ember/component';
class ContentComponent extends Component {}
export default setComponentTemplate(layout, ContentComponent);

View File

@ -0,0 +1,21 @@
/**
* @module Menu
* Menu components are contextual components of LinkableItem, used to display a menu on the right side of a LinkableItem component.
*
* @example
* ```js
* <LinkableItem as |Li|>
* <Li.menu>
* Some menu here
* </Li.menu>
* </LinkableItem>
* ```
*/
import Component from '@glimmer/component';
import layout from '../../templates/components/linkable-item/menu';
import { setComponentTemplate } from '@ember/component';
class MenuComponent extends Component {}
export default setComponentTemplate(layout, MenuComponent);

View File

@ -0,0 +1,38 @@
/**
* @module ReadMore
* ReadMore components are used to wrap long text that we'd like to show as one line initially with the option to expand and read. Text which is shorter than the surrounding div will not truncate or show the See More button.
*
* @example
* ```js
* <ReadMore>My <em>super</em> long text goes in here</ReadMore>
* ```
*/
import Component from '@glimmer/component';
import layout from '../templates/components/read-more';
import { setComponentTemplate } from '@ember/component';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
class ReadMoreComponent extends Component {
@action
calculateOverflow(e) {
const spanText = e.querySelector('.description-block');
if (spanText.offsetWidth > e.offsetWidth) {
this.hasOverflow = true;
}
}
@tracked
isOpen = false;
@tracked
hasOverflow = false;
@action
toggleOpen() {
this.isOpen = !this.isOpen;
}
}
export default setComponentTemplate(layout, ReadMoreComponent);

View File

@ -0,0 +1,17 @@
<div class="test" ...attributes>
{{#if @disabled }}
<div class="list-item-row linkable-item is-no-underline">
{{yield (hash content=(component 'linkable-item/content'))}}
{{yield (hash menu=(component 'linkable-item/menu'))}}
</div>
{{else}}
<LinkedBlock
@params={{array @link.route @link.model}}
class="list-item-row linkable-item is-no-underline"
data-test-auth-backend-link={{@link.model}}
>
{{yield (hash content=(component 'linkable-item/content'))}}
{{yield (hash menu=(component 'linkable-item/menu'))}}
</LinkedBlock>
{{/if}}
</div>

View File

@ -0,0 +1,49 @@
<div class="linkable-item-content" data-test-linkable-item-content ...attributes>
<div class="has-text-grey">
{{#if @glyph}}
<ToolTip @horizontalPosition="left" as |T|>
<T.trigger>
<Icon
@glyph={{@glyph}}
@size="l"
class="has-text-grey-light"
data-test-linkable-item-glyph
/>
</T.trigger>
<T.content @class="tool-tip">
<div class="box">
{{or @glyphText @title}}
</div>
</T.content>
</ToolTip>
{{/if}}
{{#if @title}}
{{#if @link}}
<LinkTo
@route={{@link.route}}
@model={{@link.model}}
class="has-text-black has-text-weight-semibold"
data-test-secret-path
>
{{@title}}
</LinkTo>
{{else}}
<span data-test-secret-path>{{@title}}</span>
{{/if}}
{{/if}}
</div>
{{#if @accessor}}
<code class="has-text-grey is-size-8" data-test-linkable-item-accessor>
{{@accessor}}
</code>
{{/if}}
{{#if @description}}
<ReadMore data-test-linkable-item-description>
{{@description}}
</ReadMore>
{{/if}}
{{yield}}
</div>

View File

@ -0,0 +1,3 @@
<div class="linkable-item-menu" data-test-linkable-item-menu ...attributes>
{{yield}}
</div>

View File

@ -0,0 +1,20 @@
<div class="has-text-grey has-font-weight-normal overflow-ellipsis {{if this.isOpen "" "is-closed"}} "
...attributes
{{did-insert this.calculateOverflow}}
data-test-read-more
>
<span class="description-block" data-test-readmore-content>
{{yield}}
</span>
{{#if this.hasOverflow}}
<div class="linkable-item-seemore" data-test-readmore-toggle>
<button {{on "click" this.toggleOpen}} class="link link-plain">
{{#if this.isOpen}}
See Less
{{else}}
See More
{{/if}}
</button>
</div>
{{/if}}
</div>

View File

@ -0,0 +1 @@
export { default } from 'core/components/linkable-item';

View File

@ -0,0 +1 @@
export { default } from 'core/components/linkable-item/content';

View File

@ -0,0 +1 @@
export { default } from 'core/components/linkable-item/menu';

View File

@ -0,0 +1 @@
export { default } from 'core/components/read-more';

View File

@ -0,0 +1,26 @@
<!--THIS FILE IS AUTO GENERATED. This file is generated from JSDoc comments in lib/core/addon/components/linkable-item.js. To make changes, first edit that file and run "yarn gen-story-md linkable-item" to re-generate the content.-->
## LinkableItem
LinkableItem components have two contextual components, a Content component used to show information on the left with a Menu component on the right, all aligned vertically centered. If passed a link, the block will be clickable.
**Params**
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| [link] | <code>object</code> | <code></code> | Link should have route and model |
| [disabled] | <code>boolean</code> | <code>false</code> | If no link then should be given a disabled attribute equal to true |
**Example**
```js
<LinkableItem @link={{hash route='vault.backends' model='my-backend-path'}} data-test-row="my-backend-path">
// Use <LinkableItem.content> and <LinkableItem.menu> here
</LinkableItem>
```
**See**
- [Uses of LinkableItem](https://github.com/hashicorp/vault/search?l=Handlebars&q=LinkableItem+OR+linkable-item)
- [LinkableItem Source Code](https://github.com/hashicorp/vault/blob/master/ui/lib/core/addon/components/linkable-item.js)
---

View File

@ -0,0 +1,47 @@
import hbs from 'htmlbars-inline-precompile';
import { storiesOf } from '@storybook/ember';
import { text, withKnobs, boolean } from '@storybook/addon-knobs';
import notes from './linkable-item.md';
storiesOf('LinkableItem', module)
.addParameters({ options: { showPanel: true } })
.addDecorator(withKnobs())
.add(
`LinkableItem with attributes`,
() => ({
template: hbs`
<h5 class="title is-5">Linkable Item</h5>
<LinkableItem @disabled={{disabled}} @link={{hash route="vault" model="myModel"}} as |Li|>
<Li.content @accessor={{accessor}} @link={{hash route="vault" model="myModel"}} @title={{title}} @description={{description}} />
<Li.menu>{{menu}}</Li.menu>
</LinkableItem>
`,
context: {
disabled: boolean('disabled', false),
title: text('title', 'My Title'),
accessor: text('accessor', 'v2 secret'),
description: text(
'description',
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam volutpat vulputate lacus sit amet lobortis. Nulla fermentum porta consequat. Mauris porttitor libero nibh, ac facilisis ex molestie non. Nulla dolor est, pharetra et maximus vel, varius eu augue. Maecenas eget nisl convallis, vehicula massa quis, pharetra justo. Praesent porttitor arcu at gravida dignissim. Vestibulum condimentum, risus a fermentum pulvinar, enim massa venenatis velit, a venenatis leo sem eget dolor. Morbi convallis dui sit amet egestas commodo. Nulla et ultricies leo.'
),
menu: text('menu component', 'menu button goes here'),
},
}),
{ notes }
)
.add(
`LinkableItem with blocks`,
() => ({
template: hbs`
<h5 class="title is-5">Linkable Item with block content</h5>
<LinkableItem @disabled={{disabled}} @title={{title}} @link={{hash route="vault" model="myModel"}} as |Li|>
<Li.content @accessor={{accessor}} @description={{description}} />
<Li.menu>{{menu}}</Li.menu>
</LinkableItem>
`,
context: {
disabled: boolean('disabled', false),
},
}),
{ notes }
);

View File

@ -0,0 +1,19 @@
import hbs from 'htmlbars-inline-precompile';
import { storiesOf } from '@storybook/ember';
import { withKnobs } from '@storybook/addon-knobs';
storiesOf('ReadMore', module)
.addParameters({ options: { showPanel: true } })
.addDecorator(withKnobs())
.add(`ReadMore`, () => ({
template: hbs`
<h5 class="title is-5">Read More</h5>
<h6 class="has-text-grey">NOTE: normally this component has a "See More" button when it truncates text, which is clickable and will expand the height of the outer box (shown here with a black outline).</h6>
<div style="width: 500px; border: 1px solid black;">
<ReadMore>
<strong>Anything can go in here</strong> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam volutpat vulputate lacus sit amet lobortis. Nulla fermentum porta consequat. Mauris porttitor libero nibh, ac facilisis ex molestie non. Nulla dolor est, pharetra et maximus vel, varius eu augue. Maecenas eget nisl convallis, vehicula massa quis, pharetra justo.
</ReadMore>
</div>
`,
context: {},
}));

View File

@ -44,6 +44,7 @@
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
"@babel/plugin-transform-block-scoping": "^7.12.1",
"@ember/optional-features": "^2.0.0",
"@ember/render-modifiers": "^1.0.2",
"@glimmer/component": "^1.0.2",
"@glimmer/tracking": "^1.0.2",
"@hashicorp/structure-icons": "^1.3.0",

View File

@ -25,6 +25,7 @@ module('Acceptance | alicloud/enable', function(hooks) {
await settled();
assert.equal(currentRouteName(), 'vault.cluster.secrets.backends', 'redirects to the backends page');
await settled();
assert.ok(backendsPage.rows.filterBy('path', `${enginePath}/`)[0], 'shows the alicloud engine');
});
});

View File

@ -0,0 +1,83 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | linkable-item', function(hooks) {
setupRenderingTest(hooks);
test('it renders anything passed in', async function(assert) {
await render(hbs`<LinkableItem />`);
assert.equal(this.element.textContent.trim(), '', 'No content rendered');
await render(hbs`
<LinkableItem as |Li|>
<Li.content>
stuff here
</Li.content>
<Li.menu>
menu
</Li.menu>
</LinkableItem>
`);
assert.dom('[data-test-linkable-item-content]').hasText('stuff here');
assert.dom('[data-test-linkable-item-menu]').hasText('menu');
});
test('it is not wrapped in a linked block if disabled is true', async function(assert) {
await render(hbs`
<LinkableItem @disabled={{true}} as |Li|>
<Li.content>
stuff here
</Li.content>
</LinkableItem>
`);
assert.dom('.list-item-row').exists('List item row exists');
assert.dom('.list-item-row.linked-block').doesNotExist('Does not render linked block');
assert.dom('[data-test-secret-path]').doesNotExist('Title is not rendered');
assert.dom('[data-test-linkable-item-accessor]').doesNotExist('Accessor is not rendered');
assert.dom('[data-test-linkable-item-accessor]').doesNotExist('Accessor is not rendered');
assert.dom('[data-test-linkable-item-glyph]').doesNotExist('Glyph is not rendered');
});
test('it is wrapped in a linked block if a link is passed', async function(assert) {
await render(hbs`
<LinkableItem @link={{hash route="vault" model="modelId"}} as |Li|>
<Li.content
@title={{title}}
@link={{hash route="vault" model="modelId"}}
>
stuff here
</Li.content>
</LinkableItem>
`);
assert.dom('.list-item-row.linked-block').exists('Renders linked block');
});
test('it renders standard attributes on content', async function(assert) {
this.set('title', 'A Title');
this.set('accessor', 'my accessor');
this.set('description', 'my description');
this.set('glyph', 'key');
this.set('glyphText', 'Here is some extra info');
// Template block usage:
await render(hbs`
<LinkableItem data-test-example as |Li|>
<Li.content
@accessor={{this.accessor}}
@description={{this.description}}
@glyph={{this.glyph}}
@glyphText={{this.glyphText}}
@title={{this.title}}
/>
</LinkableItem>
`);
assert.dom('.list-item-row').exists('List item row exists');
assert.dom('[data-test-secret-path]').hasText(this.title, 'Title is rendered');
assert.dom('[data-test-linkable-item-accessor]').hasText(this.accessor, 'Accessor is rendered');
assert.dom('[data-test-linkable-item-description]').hasText(this.description, 'Description is rendered');
assert.dom('[data-test-linkable-item-glyph]').exists('Glyph is rendered');
});
});

View File

@ -0,0 +1,50 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, click } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | read-more', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<ReadMore />`);
assert.equal(this.element.textContent.trim(), '');
});
test('it can toggle open and closed when text is longer than parent', async function(assert) {
this.set(
'description',
'My super long template block text dignissim dictum sem, ut varius ligula lacinia quis.'
);
await render(hbs`
<div style="width: 150px">
<ReadMore>
{{this.description}}
</ReadMore>
</div>
`);
assert.dom('[data-test-readmore-content]').includesText(this.description);
assert.dom('[data-test-readmore-toggle]').exists('toggle exists');
assert.dom('[data-test-readmore-toggle]').hasText('See More', 'Toggle should have text to see more');
assert
.dom('.overflow-ellipsis.is-closed')
.exists('Overflow div has is-closed class when more text to show');
await click('[data-test-readmore-toggle] button');
assert.dom('.overflow-ellipsis').exists('Div with overflow class still exists');
assert.dom('.overflow-ellipsis.is-closed').doesNotExist('Div with overflow class no longer is-closed');
assert.dom('[data-test-readmore-toggle]').hasText('See Less', 'Toggle should have text to see less');
});
test('it does not show show more button if parent is wider than content', async function(assert) {
this.set('description', 'Hello');
await render(hbs`
<div style="width: 150px">
<ReadMore>
{{this.description}}
</ReadMore>
</div>
`);
assert.dom('[data-test-readmore-content]').includesText(this.description);
assert.dom('[data-test-readmore-toggle]').doesNotExist('toggle exists');
assert.dom('.overflow-ellipsis').exists('Overflow div exists');
});
});

View File

@ -2,7 +2,6 @@ import { create, visitable, collection, clickable, text } from 'ember-cli-page-o
import uiPanel from 'vault/tests/pages/components/console/ui-panel';
export default create({
console: uiPanel,
consoleToggle: clickable('[data-test-console-toggle]'),
visit: visitable('/vault/secrets'),
rows: collection('[data-test-secret-backend-row]', {
@ -18,4 +17,5 @@ export default create({
confirmDisable: clickable('[data-test-confirm-button]', {
testContainer: '#ember-testing',
}),
console: uiPanel,
});

View File

@ -1228,6 +1228,14 @@
ember-cli-babel "^6.16.0"
ember-compatibility-helpers "^1.1.1"
"@ember/render-modifiers@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz#2e87c48db49d922ce4850d707215caaac60d8444"
integrity sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ==
dependencies:
ember-cli-babel "^7.10.0"
ember-modifier-manager-polyfill "^1.1.0"
"@ember/test-helpers@^1.7.1":
version "1.7.3"
resolved "https://registry.yarnpkg.com/@ember/test-helpers/-/test-helpers-1.7.3.tgz#d06b36cb579b172186b11b236b90f0a1aba15ab0"
@ -7669,6 +7677,39 @@ ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.10.0, ember-cli-babel@^6.16.0,
ember-cli-version-checker "^2.1.2"
semver "^5.5.0"
ember-cli-babel@^7.10.0:
version "7.26.6"
resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-7.26.6.tgz#322fbbd3baad9dd99e3276ff05bc6faef5e54b39"
integrity sha512-040svtfj2RC35j/WMwdWJFusZaXmNoytLAMyBDGLMSlRvznudTxZjGlPV6UupmtTBApy58cEF8Fq4a+COWoEmQ==
dependencies:
"@babel/core" "^7.12.0"
"@babel/helper-compilation-targets" "^7.12.0"
"@babel/plugin-proposal-class-properties" "^7.13.0"
"@babel/plugin-proposal-decorators" "^7.13.5"
"@babel/plugin-transform-modules-amd" "^7.13.0"
"@babel/plugin-transform-runtime" "^7.13.9"
"@babel/plugin-transform-typescript" "^7.13.0"
"@babel/polyfill" "^7.11.5"
"@babel/preset-env" "^7.12.0"
"@babel/runtime" "7.12.18"
amd-name-resolver "^1.3.1"
babel-plugin-debug-macros "^0.3.4"
babel-plugin-ember-data-packages-polyfill "^0.1.2"
babel-plugin-ember-modules-api-polyfill "^3.5.0"
babel-plugin-module-resolver "^3.2.0"
broccoli-babel-transpiler "^7.8.0"
broccoli-debug "^0.6.4"
broccoli-funnel "^2.0.2"
broccoli-source "^2.1.2"
clone "^2.1.2"
ember-cli-babel-plugin-helpers "^1.1.1"
ember-cli-version-checker "^4.1.0"
ensure-posix-path "^1.0.2"
fixturify-project "^1.10.0"
resolve-package-path "^3.1.0"
rimraf "^3.0.1"
semver "^5.5.0"
ember-cli-browserstack@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ember-cli-browserstack/-/ember-cli-browserstack-1.1.0.tgz#1d2bcf84370c196dc0c091ee65d54193072dadfc"
@ -8351,6 +8392,15 @@ ember-maybe-in-element@^0.4.0:
dependencies:
ember-cli-babel "^7.1.0"
ember-modifier-manager-polyfill@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz#cf4444e11a42ac84f5c8badd85e635df57565dda"
integrity sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA==
dependencies:
ember-cli-babel "^7.10.0"
ember-cli-version-checker "^2.1.2"
ember-compatibility-helpers "^1.2.0"
ember-native-dom-helpers@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/ember-native-dom-helpers/-/ember-native-dom-helpers-0.7.0.tgz#98a87c11a391cec5c12382a4857e59ea2fb4b00a"