Merge pull request #6626 from hashicorp/ui-toolbar

UI: Add Toolbar
This commit is contained in:
Joshua Ogle 2019-05-09 18:25:18 -06:00 committed by GitHub
commit db5a9cf201
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 1026 additions and 747 deletions

View File

@ -37,6 +37,7 @@ export const GLYPHS_WITH_SVG_TAG = [
'neutral-circled-outline', 'neutral-circled-outline',
'perf-replication', 'perf-replication',
'person', 'person',
'plus-plain',
'role', 'role',
'status-indicator', 'status-indicator',
'stopwatch', 'stopwatch',

View File

@ -9,4 +9,5 @@ export default Component.extend({
baseKey: null, baseKey: null,
backendCrumb: null, backendCrumb: null,
model: null, model: null,
options: null,
}); });

View File

@ -0,0 +1,3 @@
import OuterHTML from './outer-html';
export default OuterHTML.extend({});

View File

@ -0,0 +1,5 @@
import DownloadButton from './download-button';
export default DownloadButton.extend({
classNames: ['toolbar-link'],
});

View File

@ -0,0 +1,3 @@
import OuterHTML from './outer-html';
export default OuterHTML.extend({});

View File

@ -0,0 +1,15 @@
import OuterHTML from './outer-html';
import { computed } from '@ember/object';
export default OuterHTML.extend({
glyph: computed('type', function() {
if (this.type == 'add') {
return 'plus-plain';
} else {
return 'chevron-right';
}
}),
tagName: '',
type: null,
supportsDataTestProperties: true,
});

View File

@ -0,0 +1,14 @@
import OuterHTML from './outer-html';
import { computed } from '@ember/object';
export default OuterHTML.extend({
glyph: computed('type', function() {
if (this.type == 'add') {
return 'plus-plain';
} else {
return 'chevron-right';
}
}),
tagName: '',
supportsDataTestProperties: true,
});

View File

@ -0,0 +1,6 @@
import OuterHTML from './outer-html';
export default OuterHTML.extend({
classNames: ['toolbar'],
tagName: 'nav',
});

View File

@ -0,0 +1,9 @@
import { computed } from '@ember/object';
import Controller from '@ember/controller';
export default Controller.extend({
isConfigurable: computed('model.type', function() {
const configurableEngines = ['aws', 'ssh', 'pki'];
return configurableEngines.includes(this.get('model.type'));
}),
});

View File

@ -16,6 +16,10 @@ export default Controller.extend(ListController, BackendCrumbMixin, WithNavToNea
return !!utils.keyIsFolder(this.get('filter')); return !!utils.keyIsFolder(this.get('filter'));
}), }),
isConfigurableTab: computed('isCertTab', 'isConfigure', function() {
return this.get('isCertTab') || this.get('isConfigure');
}),
actions: { actions: {
chooseAction(action) { chooseAction(action) {
this.set('selectedAction', action); this.set('selectedAction', action);

View File

@ -18,3 +18,19 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.toolbar-namespace-picker {
padding: 0 $spacing-s;
.field {
width: 100%;
}
.field-label {
margin-right: $spacing-s;
}
.is-label {
color: $grey;
}
}

View File

@ -9,7 +9,7 @@
&.thead { &.thead {
box-shadow: 0 1px 0 $grey-light, 0 -1px 0 $grey-light; box-shadow: 0 1px 0 $grey-light, 0 -1px 0 $grey-light;
margin: 0; margin: 0;
padding: 0 $size-6; padding: 0 $size-6 0 0;
.column { .column {
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;

View File

@ -1,24 +0,0 @@
.secret-control-bar {
margin: 0;
padding: $size-10 $size-9;
background: $grey-lighter;
box-shadow: 0 1px 0 $grey-light, 0 -1px 0 $grey-light;
display: flex;
justify-content: flex-end;
.control {
flex: 0 1 auto;
padding: 0 $size-10;
font-size: $size-8;
height: 1.8rem;
line-height: 1.8rem;
display: flex;
flex-direction: column;
justify-content: center;
.switch[type='checkbox'].is-small + label::before {
top: 0.5rem;
}
.switch[type='checkbox'].is-small + label::after {
top: 0.6rem;
}
}
}

View File

@ -1,3 +1,7 @@
.page-header + .tabs-container {
box-shadow: none;
}
.tabs { .tabs {
box-shadow: inset 0 -1px 0 $grey-light; box-shadow: inset 0 -1px 0 $grey-light;
@ -15,25 +19,25 @@
border-color: $blue; border-color: $blue;
color: $blue; color: $blue;
} }
&:first-child a,
&:first-child .tab {
margin-left: $size-5;
}
} }
a, a,
.tab { .tab {
color: $grey-dark; color: $grey;
font-weight: $font-weight-semibold; font-weight: $font-weight-semibold;
text-decoration: none; text-decoration: none;
padding: $size-6 $size-8 $size-8; padding: $size-6 $size-8 $size-8;
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
transition: border-color $speed; transition: background-color $speed, border-color $speed;
&:hover, &:hover,
&:active { &:active {
border-color: $grey-light; border-color: $grey-light;
} }
&:hover {
background-color: $ui-gray-050;
}
} }
.ember-basic-dropdown-trigger { .ember-basic-dropdown-trigger {

View File

@ -0,0 +1,98 @@
.tabs-container + .toolbar {
border-top: 0;
}
.toolbar {
background-color: $ui-gray-010;
border: 1px solid $ui-gray-100;
border-bottom-color: $ui-gray-300;
border-top-color: $ui-gray-300;
position: relative;
&::after {
background: linear-gradient(to right, $ui-gray-010, rgba($ui-gray-010, 0));
bottom: 0;
content: '';
position: absolute;
right: 0;
top: 0;
width: $spacing-xxs;
z-index: 2;
}
.input,
.select {
min-width: 160px;
}
}
.toolbar-scroller {
align-items: center;
display: flex;
height: 44px;
justify-content: space-between;
overflow-x: auto;
width: 100%;
@include from($mobile) {
padding: 0 $spacing-xxs;
}
&::-webkit-scrollbar {
border-bottom: $base-border;
height: $spacing-xxs;
}
&::-webkit-scrollbar-thumb {
background: $ui-gray-300;
border-radius: $spacing-xxs;
}
}
.toolbar-filters,
.toolbar-actions {
align-items: center;
display: flex;
flex: 1;
white-space: nowrap;
}
.toolbar-filters + .toolbar-actions {
@include until($mobile) {
border-left: $base-border;
margin-left: $spacing-xs;
padding-left: $spacing-xs;
}
}
.toolbar-actions {
@include from($mobile) {
justify-content: flex-end;
}
}
.toolbar-link {
@extend .button;
@extend .is-ghost;
@extend .has-icon-right;
border: 0;
color: $black;
transition: background-color $speed;
&:hover {
background-color: $ui-gray-100;
border: 0;
color: $blue;
}
&:active {
box-shadow: none;
}
}
.toolbar-separator {
border-right: $light-border;
height: 32px;
margin: 0 $spacing-xs;
width: 0;
}

View File

@ -71,13 +71,13 @@
@import './components/radial-progress'; @import './components/radial-progress';
@import './components/role-item'; @import './components/role-item';
@import './components/search-select'; @import './components/search-select';
@import './components/secret-control-bar';
@import './components/shamir-progress'; @import './components/shamir-progress';
@import './components/sidebar'; @import './components/sidebar';
@import './components/splash-page'; @import './components/splash-page';
@import './components/status-menu'; @import './components/status-menu';
@import './components/tabs'; @import './components/tabs';
@import './components/token-expire-warning'; @import './components/token-expire-warning';
@import './components/toolbar';
@import './components/tool-tip'; @import './components/tool-tip';
@import './components/unseal-warning'; @import './components/unseal-warning';
@import './components/upgrade-overlay'; @import './components/upgrade-overlay';

View File

@ -192,8 +192,8 @@ $button-box-shadow-standard: 0 3px 1px 0 rgba($black, 0.12);
.icon { .icon {
&, &,
&:first-child:last-child { &:first-child:last-child {
margin-left: $size-11; margin-left: $spacing-xxs;
margin-right: -$size-10; margin-right: -$spacing-xxs;
} }
} }
} }

View File

@ -1,16 +1,14 @@
.table { .table {
thead, thead,
.thead { .thead {
background: $grey-lighter;
box-shadow: 0 1px 0 0 $grey-light, 0 -1px 0 0 $grey-light; box-shadow: 0 1px 0 0 $grey-light, 0 -1px 0 0 $grey-light;
th, th,
.th { .th {
text-transform: uppercase;
font-size: $size-8; font-size: $size-8;
color: $grey-dark; color: $grey;
font-weight: normal; font-weight: $font-weight-semibold;
padding: 0.5rem 1.5rem; padding: 1rem 1.5rem 0;
border-width: 0 0 1px 0; border-width: 0 0 1px 0;
border-color: $grey-light; border-color: $grey-light;
} }

View File

@ -4,20 +4,8 @@
{{capitalize (pluralize identityType)}} {{capitalize (pluralize identityType)}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#if (eq identityType "entity")}}
{{#link-to "vault.cluster.access.identity.merge" (pluralize identityType) class="button has-icon-right is-ghost is-compact" data-test-entity-merge-link=true}}
Merge {{pluralize identityType}}
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
{{/if}}
{{#link-to "vault.cluster.access.identity.create" (pluralize identityType) class="button has-icon-right is-ghost is-compact" data-test-entity-create-link=true}}
Create {{identityType}}
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
<div class="box is-sideless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
{{#link-to "vault.cluster.access.identity.index" (pluralize identityType) tagName="li"}} {{#link-to "vault.cluster.access.identity.index" (pluralize identityType) tagName="li"}}
@ -33,12 +21,27 @@
</ul> </ul>
</nav> </nav>
</div> </div>
<Toolbar>
{{#if model.meta.total}} {{#if model.meta.total}}
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless"> <ToolbarFilters>
<div class="level">
<div class="level-left">
{{identity/lookup-input type=identityType}} {{identity/lookup-input type=identityType}}
</div> </ToolbarFilters>
</div>
</div>
{{/if}} {{/if}}
<ToolbarActions>
{{#if (eq identityType "entity")}}
<ToolbarLink
@params={{array "vault.cluster.access.identity.merge" (pluralize identityType)}}
@data-test-entity-merge-link=true
>
Merge {{pluralize identityType}}
</ToolbarLink>
{{/if}}
<ToolbarLink
@type="add"
@params={{array "vault.cluster.access.identity.create" (pluralize identityType)}}
@data-test-entity-create-link=true
>
Create {{identityType}}
</ToolbarLink>
</ToolbarActions>
</Toolbar>

View File

@ -1,5 +1,5 @@
<form {{action (perform lookup) on="submit"}}> <form {{action (perform lookup) on="submit"}}>
<div class="field has-addons"> <div class="field is-flex">
<div class="control"> <div class="control">
<div class="select is-fullwidth"> <div class="select is-fullwidth">
<select <select

View File

@ -14,6 +14,6 @@
onblur={{action "setFilterFocused" false}} onblur={{action "setFilterFocused" false}}
/> />
{{i-con glyph="ios-search-strong" class="is-left has-text-grey" size=18}} {{i-con glyph="ios-search-strong" class="is-left has-text-grey-light" size=20}}
</p> </p>
</div> </div>

View File

@ -19,39 +19,32 @@
{{/if}} {{/if}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight> </PageHeader>
<div class="field is-grouped">
<Toolbar>
<ToolbarActions>
{{#if (eq mode "show")}} {{#if (eq mode "show")}}
{{#if (or model.canUpdate model.canDelete)}} {{#if (or model.canUpdate model.canDelete)}}
<div class="control"> <ToolbarSecretLink
{{#secret-link @secret={{model.id}}
secret=model.id @mode="edit"
mode="edit" @replace=true
replace=true >
class="button has-icon-right is-ghost is-compact"
}}
Edit role Edit role
{{i-con glyph="chevron-right" size=11}} </ToolbarSecretLink>
{{/secret-link}}
</div>
{{/if}} {{/if}}
{{#if model.canGenerate}} {{#if model.canGenerate}}
<div class="control"> <ToolbarSecretLink
{{#secret-link @secret={{model.id}}
mode="credentials" @mode="credentials"
secret=model.id @data-test-backend-credentials="iam"
class="button has-icon-right is-ghost is-compact" >
data-test-backend-credentials="iam"
}}
Generate credentials Generate credentials
{{i-con glyph="chevron-right" size=11}} </ToolbarSecretLink>
{{/secret-link}}
</div>
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </ToolbarActions>
</p.levelRight> </Toolbar>
</PageHeader>
{{#if (or (eq mode 'edit') (eq mode 'create'))}} {{#if (or (eq mode 'edit') (eq mode 'create'))}}
{{partial 'partials/role-aws/form'}} {{partial 'partials/role-aws/form'}}

View File

@ -19,55 +19,44 @@
{{/if}} {{/if}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight> </PageHeader>
<div class="field is-grouped">
<Toolbar>
<ToolbarActions>
{{#if (eq mode "show") }} {{#if (eq mode "show") }}
{{#if (or model.canUpdate model.canDelete)}} {{#if (or model.canUpdate model.canDelete)}}
<div class="control"> <ToolbarSecretLink
{{#secret-link @secret={{model.id}}
secret=model.id @mode="edit"
mode="edit" @data-test-edit-link=true
replace=true @replace=true
class="button has-icon-right is-ghost is-compact" >
data-test-edit-link=true
}}
Edit role Edit role
{{i-con glyph="chevron-right" size=11}} </ToolbarSecretLink>
{{/secret-link}}
</div>
{{/if}} {{/if}}
{{#if model.canGenerate}} {{#if model.canGenerate}}
<div class="control"> <ToolbarSecretLink
{{#secret-link @secret={{model.id}}
mode="credentials" @mode="credentials"
secret=model.id @queryParams={{query-params action="issue"}}
queryParams=(query-params action="issue") @data-test-credentials-link=true
class="button has-icon-right is-ghost is-compact" >
data-test-credentials-link=true
}}
Generate Certificate Generate Certificate
{{i-con glyph="chevron-right" size=11}} </ToolbarSecretLink>
{{/secret-link}}
</div>
{{/if}} {{/if}}
{{#if model.canSign}} {{#if model.canSign}}
<div class="control"> <ToolbarSecretLink
{{#secret-link @secret={{model.id}}
mode="credentials" @mode="credentials"
secret=model.id @queryParams={{query-params action="sign"}}
queryParams=(query-params action="sign") @data-test-sign-link=true
class="button has-icon-right is-ghost is-compact" >
data-test-sign-link=true
}}
Sign Certificate Sign Certificate
{{i-con glyph="chevron-right" size=11}} </ToolbarSecretLink>
{{/secret-link}}
</div>
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </ToolbarActions>
</p.levelRight> </Toolbar>
</PageHeader>
{{#if (or (eq mode 'edit') (eq mode 'create'))}} {{#if (or (eq mode 'edit') (eq mode 'create'))}}
{{partial 'partials/role-pki/form'}} {{partial 'partials/role-pki/form'}}

View File

@ -19,51 +19,44 @@
{{/if}} {{/if}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
<div class="field is-grouped">
{{#if (eq mode "show") }}
{{#if (or model.canUpdate model.canDelete)}}
<div class="control">
{{#secret-link
secret=model.id
mode="edit"
replace=true
class="button has-icon-right is-ghost is-compact"
data-test-edit-link=true
}}
Edit role
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
</div>
{{/if}}
<div class="control">
{{#if (eq model.keyType "otp")}}
{{#secret-link
mode="credentials"
secret=model.id
class="button has-icon-right is-ghost is-compact"
data-test-backend-credentials=true
}}
Generate credentials
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
{{else}}
{{#secret-link
mode="sign"
secret=model.id
class="button has-icon-right is-ghost is-compact"
data-test-backend-credentials=true
}}
Sign keys
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
{{/if}}
</div>
{{/if}}
</div>
</p.levelRight>
</PageHeader> </PageHeader>
{{#if (eq mode "show") }}
<Toolbar>
<ToolbarActions>
{{#if (or model.canUpdate model.canDelete)}}
<ToolbarSecretLink
@secret={{model.id}}
@mode="edit"
@data-test-edit-link=true
@replace=true
>
Edit role
</ToolbarSecretLink>
{{/if}}
{{#if (eq model.keyType "otp")}}
<ToolbarSecretLink
@secret={{model.id}}
@mode="credentials"
@data-test-backend-credentials=true
@replace=true
>
Generate Credential
</ToolbarSecretLink>
{{else}}
<ToolbarSecretLink
@secret={{model.id}}
@mode="sign"
@data-test-backend-credentials=true
@replace=true
>
Sign Keys
</ToolbarSecretLink>
{{/if}}
</ToolbarActions>
</Toolbar>
{{/if}}
{{#if (or (eq mode 'edit') (eq mode 'create'))}} {{#if (or (eq mode 'edit') (eq mode 'create'))}}
{{partial 'partials/role-ssh/form'}} {{partial 'partials/role-ssh/form'}}
{{else}} {{else}}

View File

@ -21,26 +21,11 @@
{{/if}} {{/if}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#if canDelete}}
<ConfirmAction
@buttonClasses="button is-compact is-ghost has-icon-right"
@onConfirmAction={{action "deleteKey"}}
@confirmMessage={{if isV2
(concat "This will permanently delete " model.id " and all its versions. Are you sure you want to do this?")
(concat "Are you sure you want to delete " model.id "?")
}}
@cancelButtonText="Cancel"
data-test-secret-delete="true"
>
Delete secret <ICon @glyph="chevron-right" @size="11" />
</ConfirmAction>
{{/if}}
</p.levelRight>
</PageHeader> </PageHeader>
<div class="secret-control-bar">
<Toolbar>
{{#unless (and (eq mode 'show') isWriteWithoutRead)}} {{#unless (and (eq mode 'show') isWriteWithoutRead)}}
<div class="control"> <ToolbarFilters>
<input <input
data-test-secret-json-toggle=true data-test-secret-json-toggle=true
id="json" id="json"
@ -52,12 +37,81 @@
disabled={{and (eq mode 'show') secretDataIsAdvanced}} disabled={{and (eq mode 'show') secretDataIsAdvanced}}
/> />
<label for="json" class="has-text-grey">JSON</label> <label for="json" class="has-text-grey">JSON</label>
</div> </ToolbarFilters>
{{/unless}} {{/unless}}
<ToolbarActions>
{{#if (and (eq @mode "show") this.isV2 (not @model.failedServerRead))}}
<SecretVersionMenu
@version={{this.modelForData}}
@onRefresh={{action 'refresh'}}
/>
<BasicDropdown
@class="popup-menu"
@horizontalPosition="auto-right"
@verticalPosition="below"
as |D|
>
<D.trigger
data-test-popup-menu-trigger="true"
@class={{concat "popup-menu-trigger toolbar-link" (if D.isOpen " is-active")}}
@tagName="button"
>
History
<ICon @glyph="chevron-down" @size="12" />
</D.trigger>
<D.content @class="popup-menu-content ">
<nav class="box menu">
<ul class="menu-list">
<li class="action">
<SecretLink
@mode="versions"
@secret={{this.model.id}}
@class="has-text-black has-text-weight-semibold has-bottom-shadow"
>
View version history
</SecretLink>
</li>
</ul>
<h5 class="list-header">Versions</h5>
<ul class="menu-list">
{{#each (reverse this.model.versions) as |secretVersion|}}
<li class="action">
<LinkTo class="link" @params={{array (query-params version=secretVersion.version)}}>
Version {{secretVersion.version}}
{{#if (eq secretVersion.version this.model.currentVersion)}}
<ICon @glyph="checkmark-circled-outline" @excludeIconClass={{true}} @size="13" @class="has-text-success is-pulled-right" />
{{else if secretVersion.deleted}}
<ICon @glyph="cancel-square-outline" @size="13" @excludeIconClass={{true}} @class="has-text-grey is-pulled-right" />
{{/if}}
</LinkTo>
</li>
{{/each}}
</ul>
</nav>
</D.content>
</BasicDropdown>
<div class="toolbar-separator"/>
{{/if}}
{{#if (and (eq mode 'show') canDelete)}}
<ConfirmAction
@buttonClasses="toolbar-link"
@onConfirmAction={{action "deleteKey"}}
@confirmMessage={{if isV2
(concat "This will permanently delete " model.id " and all its versions. Are you sure you want to do this?")
(concat "Are you sure you want to delete " model.id "?")
}}
@cancelButtonText="Cancel"
data-test-secret-delete="true"
>
Delete secret
<ICon @glyph="chevron-right" @size="12" />
</ConfirmAction>
{{/if}}
{{#if (and (eq mode 'show') (or canEditV2Secret canEdit))}} {{#if (and (eq mode 'show') (or canEditV2Secret canEdit))}}
{{#let (concat 'vault.cluster.secrets.backend.' (if (eq mode 'show') 'edit' 'show')) as |targetRoute|}} {{#let (concat 'vault.cluster.secrets.backend.' (if (eq mode 'show') 'edit' 'show')) as |targetRoute|}}
{{#unless (and isV2 (or isWriteWithoutRead modelForData.destroyed modelForData.deleted))}} {{#unless (and isV2 (or isWriteWithoutRead modelForData.destroyed modelForData.deleted))}}
<div class="control">
<BasicDropdown <BasicDropdown
@class="popup-menu" @class="popup-menu"
@horizontalPosition="auto-right" @horizontalPosition="auto-right"
@ -67,10 +121,11 @@
> >
<D.trigger <D.trigger
data-test-popup-menu-trigger="true" data-test-popup-menu-trigger="true"
@class={{concat "link link-plain has-text-weight-semibold" (if D.isOpen " is-active")}} @class={{concat "toolbar-link" (if D.isOpen " is-active")}}
@tagName="button" @tagName="button"
> >
Copy secret Copy secret
<ICon @glyph="chevron-down" @size="12" />
</D.trigger> </D.trigger>
<D.content @class="popup-menu-content is-wide"> <D.content @class="popup-menu-content is-wide">
<nav class="box menu"> <nav class="box menu">
@ -111,84 +166,29 @@
</nav> </nav>
</D.content> </D.content>
</BasicDropdown> </BasicDropdown>
</div>
{{/unless}} {{/unless}}
<div class="control">
{{#if isV2}} {{#if isV2}}
<LinkTo <ToolbarLink
@params={{array targetRoute model.id (query-params version=this.modelForData.version)}} @params={{array targetRoute model.id (query-params version=this.modelForData.version)}}
@data-test-secret-edit="true"
@replace={{true}} @replace={{true}}
class="link link-plain has-text-weight-semibold" @type="add"
data-test-secret-edit="true"
> >
Create new version Create new version
</LinkTo> </ToolbarLink>
{{else}} {{else}}
<LinkTo <ToolbarLink
@params={{array targetRoute model.id}} @params={{array targetRoute model.id}}
@data-test-secret-edit="true"
@replace={{true}} @replace={{true}}
class="link link-plain has-text-weight-semibold"
data-test-secret-edit="true"
> >
Edit secret Edit secret
</LinkTo> </ToolbarLink>
{{/if}} {{/if}}
</div>
{{/let}} {{/let}}
{{/if}} {{/if}}
{{#if (and (eq @mode "show") this.isV2 (not @model.failedServerRead))}} </ToolbarActions>
<div class="control"> </Toolbar>
<SecretVersionMenu
@version={{this.modelForData}}
@onRefresh={{action 'refresh'}}
/>
</div>
<div class="control">
<BasicDropdown
@class="popup-menu"
@horizontalPosition="auto-right"
@verticalPosition="below"
as |D|
>
<D.trigger
data-test-popup-menu-trigger="true"
@class={{concat "popup-menu-trigger button is-ghost has-text-grey" (if D.isOpen " is-active")}}
@tagName="button"
>
History <ICon @glyph="chevron-right" @size="11" />
</D.trigger>
<D.content @class="popup-menu-content ">
<nav class="box menu">
<ul class="menu-list">
<li class="action">
<SecretLink
@mode="versions"
@secret={{this.model.id}}
@class="has-text-black has-text-weight-semibold has-bottom-shadow"
>
View version history
</SecretLink>
</li>
</ul>
<h5 class="list-header">Versions</h5>
<ul class="menu-list">
{{#each (reverse this.model.versions) as |secretVersion|}}
<li class="action">
<LinkTo class="link" @params={{array (query-params version=secretVersion.version)}}>
Version {{secretVersion.version}}
{{#if (eq secretVersion.version this.model.currentVersion)}}
<ICon @glyph="checkmark-circled-outline" @excludeIconClass={{true}} @size="13" @class="has-text-success is-pulled-right" />
{{else if secretVersion.deleted}}
<ICon @glyph="cancel-square-outline" @size="13" @excludeIconClass={{true}} @class="has-text-grey is-pulled-right" />
{{/if}}
</LinkTo>
</li>
{{/each}}
</ul>
</nav>
</D.content>
</BasicDropdown>
</div>
{{/if}}
</div>
{{partial partialName}} {{partial partialName}}

View File

@ -25,35 +25,9 @@
{{/if}} {{/if}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#unless (or isCertTab isConfigure)}}
<div class="control">
{{#secret-link
mode="create"
secret=''
queryParams=(query-params initialKey=(or filter baseKey.id))
class="button has-icon-right is-ghost is-compact"
data-test-secret-create=true
}}
{{options.create}}
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
</div>
{{/unless}}
{{#if (or (eq model.type "aws") (eq model.type "ssh") (eq model.type "pki"))}}
<div class="control">
{{#link-to "vault.cluster.settings.configure-secret-backend" model.id
class="button has-icon-right is-ghost is-compact"
data-test-secret-backend-configure=true
}}
Configure {{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</div>
{{/if}}
</p.levelRight>
</PageHeader> </PageHeader>
{{#if options.tabs}} {{#if options.tabs}}
<div class="box is-bottomless is-marginless is-fullwidth is-paddingless"> <div class="tabs-container box is-bottomless is-marginless is-fullwidth is-paddingless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
{{#each options.tabs as |oTab|}} {{#each options.tabs as |oTab|}}
@ -72,7 +46,7 @@
{{/if}} {{/if}}
{{/each}} {{/each}}
{{#link-to 'vault.cluster.secrets.backend.configuration' tagName="li" activeClass="is-active"}} {{#link-to 'vault.cluster.secrets.backend.configuration' tagName="li" activeClass="is-active"}}
{{#link-to 'vault.cluster.secrets.backend.configuration' }} {{#link-to 'vault.cluster.secrets.backend.configuration' data-test-configuration-tab=true}}
Configuration Configuration
{{/link-to}} {{/link-to}}
{{/link-to}} {{/link-to}}
@ -81,7 +55,7 @@
</div> </div>
{{else}} {{else}}
{{!-- if there are no tabs in the options, we'll hardcode them here --}} {{!-- if there are no tabs in the options, we'll hardcode them here --}}
<div class="box is-bottomless is-marginless is-fullwidth is-paddingless"> <div class="tabs-container box is-bottomless is-marginless is-fullwidth is-paddingless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
{{#if (contains model.engineType (supported-secret-backends))}} {{#if (contains model.engineType (supported-secret-backends))}}
@ -92,7 +66,7 @@
{{/link-to}} {{/link-to}}
{{/if}} {{/if}}
{{#link-to 'vault.cluster.secrets.backend.configuration' tagName="li" activeClass="is-active"}} {{#link-to 'vault.cluster.secrets.backend.configuration' tagName="li" activeClass="is-active"}}
{{#link-to 'vault.cluster.secrets.backend.configuration' }} {{#link-to 'vault.cluster.secrets.backend.configuration' data-test-configuration-tab=true}}
Configuration Configuration
{{/link-to}} {{/link-to}}
{{/link-to}} {{/link-to}}

View File

@ -6,14 +6,14 @@
> >
<D.trigger <D.trigger
data-test-popup-menu-trigger="true" data-test-popup-menu-trigger="true"
@class={{concat "popup-menu-trigger button is-ghost has-text-grey" (if D.isOpen " is-active")}} @class={{concat "toolbar-link" (if D.isOpen " is-active")}}
@tagName="button" @tagName="button"
> >
{{#if useDefaultTrigger}} {{#if useDefaultTrigger}}
<ICon aria-label="More options" @glyph="more" @size="16" @class="has-text-black auto-width" /> <ICon aria-label="More options" @glyph="more" @size="16" @class="has-text-black auto-width" />
{{else}} {{else}}
Version {{this.version.version}} Version {{this.version.version}}
<ICon @glyph="chevron-right" @size="11" /> <ICon @glyph="chevron-down" @size="12" />
{{/if}} {{/if}}
</D.trigger> </D.trigger>
<D.content @class="popup-menu-content "> <D.content @class="popup-menu-content ">

View File

@ -1,6 +1,6 @@
{{#with (tabs-for-auth-section model.type tabType) as |tabs|}} {{#with (tabs-for-auth-section model.type tabType) as |tabs|}}
{{#if tabs.length}} {{#if tabs.length}}
<div class="box is-sideless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
{{#each tabs as |tab|}} {{#each tabs as |tab|}}

View File

@ -0,0 +1,3 @@
<nav class="toolbar-actions">
{{yield}}
</nav>

View File

@ -0,0 +1,2 @@
{{@actionText}}
<ICon @glyph="chevron-right" @size=11 />

View File

@ -0,0 +1,3 @@
<nav class="toolbar-filters">
{{yield}}
</nav>

View File

@ -0,0 +1,18 @@
<LinkTo
class="toolbar-link"
@params={{params}}
data-test-secret-edit={{data-test-secret-edit}}
data-test-secondary-add={{data-test-secondary-add}}
data-test-configure-link={{data-test-configure-link}}
data-test-alias-edit-link={{data-test-alias-edit-link}}
data-test-entity-edit-link={{data-test-entity-edit-link}}
data-test-entity-merge-link={{data-test-entity-merge-link}}
data-test-backend-view-link={{data-test-backend-view-link}}
data-test-entity-create-link={{data-test-entity-create-link}}
data-test-policy-create-link={{data-test-policy-create-link}}
data-test-policy-edit-toggle={{data-test-policy-edit-toggle}}
data-test-secret-backend-configure={{data-test-secret-backend-configure}}
>
{{yield}}
<ICon @glyph={{glyph}} @size=12 />
</LinkTo>

View File

@ -0,0 +1,18 @@
<SecretLink
class="toolbar-link"
@mode={{mode}}
@secret={{secret}}
@replace={{replace}}
@queryParams={{queryParams}}
@data-test-edit-link={{data-test-edit-link}}
@data-test-sign-link={{data-test-sign-link}}
@data-test-transit-link={{data-test-transit-link}}
@data-test-secret-create={{data-test-secret-create}}
@data-test-credentials-link={{data-test-credentials-link}}
@data-test-backend-credentials={{data-test-backend-credentials}}
@data-test-transit-action-link={{data-test-transit-action-link}}
@data-test-transit-key-actions-link={{data-test-transit-key-actions-link}}
>
{{yield}}
<ICon @glyph={{glyph}} @size=12 />
</SecretLink>

View File

@ -0,0 +1,3 @@
<div class="toolbar-scroller">
{{yield}}
</div>

View File

@ -19,36 +19,6 @@
{{/if}} {{/if}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
<div class="field is-grouped">
{{#if (eq mode "show") }}
{{#if (or capabilities.canUpdate capabilities.canDelete)}}
<div class="control">
{{#secret-link
secret=key.id
mode="edit"
replace=true
class="button has-icon-right is-ghost is-compact"
}}
Edit encryption key
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
</div>
{{/if}}
<div class="control">
{{#secret-link
mode="actions"
secret=key.id
class="button has-icon-right is-ghost is-compact"
data-test-transit-key-actions-link=true
}}
Key actions
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
</div>
{{/if}}
</div>
</p.levelRight>
</PageHeader> </PageHeader>
{{partial (concat 'partials/transit-form-' mode)}} {{partial (concat 'partials/transit-form-' mode)}}

View File

@ -1,9 +1,7 @@
{{#if (eq selectedAction 'rotate')}} {{#if (eq selectedAction 'rotate')}}
{{#if key.canRotate}} {{#if key.canRotate}}
<div class="field is-grouped is-grouped-split box is-fullwidth is-bottomless">
<div class="level-right is-fullwidth">
{{#confirm-action {{#confirm-action
buttonClasses="button" buttonClasses="toolbar-link"
onConfirmAction=(action "doSubmit") onConfirmAction=(action "doSubmit")
confirmMessage=(concat 'Are you sure you want to rotate "' key.id '"?') confirmMessage=(concat 'Are you sure you want to rotate "' key.id '"?')
confirmButtonText="Confirm rotation" confirmButtonText="Confirm rotation"
@ -12,9 +10,8 @@
data-test-transit-key-rotate=true data-test-transit-key-rotate=true
}} }}
Rotate encryption key Rotate encryption key
<ICon @glyph="chevron-right" @size=12 />
{{/confirm-action}} {{/confirm-action}}
</div>
</div>
{{/if}} {{/if}}
{{else}} {{else}}
{{message-error errors=errors}} {{message-error errors=errors}}

View File

@ -1,4 +1,4 @@
<div class="box is-sideless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
{{#link-to "vault.cluster.settings.configure-secret-backend" model.id (query-params tab='') tagName="li"}} {{#link-to "vault.cluster.settings.configure-secret-backend" model.id (query-params tab='') tagName="li"}}
@ -15,6 +15,7 @@
</ul> </ul>
</nav> </nav>
</div> </div>
{{#if (eq tab "leases")}} {{#if (eq tab "leases")}}
<form <form
{{action "save" "saveAWSLease" (hash lease=model.lease lease_max=model.leaseMax) on="submit"}} {{action "save" "saveAWSLease" (hash lease=model.lease lease_max=model.leaseMax) on="submit"}}

View File

@ -1,4 +1,4 @@
<div class="box is-bottomless is-fullwidth is-paddingless"> <div class="tabs-container box is-bottomless is-fullwidth is-paddingless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
{{#each (array 'cert' 'urls' 'crl' 'tidy') as |section|}} {{#each (array 'cert' 'urls' 'crl' 'tidy') as |section|}}

View File

@ -1,4 +1,4 @@
<div class="box is-sideless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs"> <nav class="tabs">
<ul> <ul>
<li class="{{if (eq tab '') 'is-active'}}"> <li class="{{if (eq tab '') 'is-active'}}">
@ -28,6 +28,37 @@
</nav> </nav>
</div> </div>
<Toolbar>
<ToolbarActions>
{{#if (eq tab 'versions')}}
<TransitKeyActions
@key={{key}}
@selectedAction="rotate"
@capabilities={{capabilities}}
@onRefresh={{action "refresh"}}
/>
{{/if}}
{{#if (eq mode "show") }}
{{#if (or capabilities.canUpdate capabilities.canDelete)}}
<ToolbarSecretLink
@secret={{key.id}}
@mode="edit"
replace=true
>
Edit encryption key
</ToolbarSecretLink>
{{/if}}
<ToolbarSecretLink
@secret={{key.id}}
@mode="actions"
@data-test-transit-key-actions-link=true
>
Key actions
</ToolbarSecretLink>
{{/if}}
</ToolbarActions>
</Toolbar>
{{#if (eq tab 'versions')}} {{#if (eq tab 'versions')}}
{{#if (or {{#if (or
(eq key.type "aes256-gcm96") (eq key.type "aes256-gcm96")
@ -161,14 +192,6 @@
{{/if}} {{/if}}
{{/each-in}} {{/each-in}}
{{/if}} {{/if}}
<p>
{{transit-key-actions
key=key
selectedAction="rotate"
capabilities=capabilities
onRefresh=(action "refresh")
}}
</p>
{{else}} {{else}}
{{info-table-row label="Type" value=key.type}} {{info-table-row label="Type" value=key.type}}
{{info-table-row label="Deletion allowed" value=(stringify key.deletionAllowed)}} {{info-table-row label="Deletion allowed" value=(stringify key.deletionAllowed)}}

View File

@ -1,3 +1,3 @@
<svg width="{{size}}" height="{{size}}" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> <svg width="{{size}}" height="{{size}}" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M8.338 2.255a.79.79 0 0 0-.645 0L.657 5.378c-.363.162-.534.538-.534.875 0 .337.171.713.534.875l1.436.637c-.332.495-.638 1.18-.744 2.106a.887.887 0 0 0-.26 1.559c.02.081.03.215.013.392-.02.205-.074.43-.162.636-.186.431-.45.64-.741.64v.98c.651 0 1.108-.365 1.403-.797l.06.073c.32.372.826.763 1.455.763v-.98c-.215 0-.474-.145-.71-.42-.111-.13-.2-.27-.259-.393a1.014 1.014 0 0 1-.06-.155c-.01-.036-.013-.055-.013-.058h-.022a2.544 2.544 0 0 0 .031-.641.886.886 0 0 0-.006-1.51c.1-.868.398-1.477.699-1.891l.332.147-.023.746v2.228c0 .115.04.22.105.304.124.276.343.5.587.677.297.217.675.396 1.097.54.846.288 1.943.456 3.127.456 1.185 0 2.281-.168 3.128-.456.422-.144.8-.323 1.097-.54.244-.177.462-.401.586-.677a.488.488 0 0 0 .106-.304V8.218l2.455-1.09c.363-.162.534-.538.534-.875 0-.337-.17-.713-.534-.875L8.338 2.255zm-.34 2.955L3.64 7.38l4.375 1.942 6.912-3.069-6.912-3.07-6.912 3.07 1.665.74 4.901-2.44.328.657zM14.307 1H12.5a.5.5 0 1 1 0-1h3a.499.499 0 0 1 .5.65V3.5a.5.5 0 1 1-1 0V1.72l-1.793 1.774a.5.5 0 0 1-.713-.701L14.307 1zm-2.368 7.653v2.383a.436.436 0 0 0-.007.021c-.017.063-.084.178-.282.322-.193.14-.473.28-.836.404-.724.247-1.71.404-2.812.404-1.1 0-2.087-.157-2.811-.404a3.188 3.188 0 0 1-.836-.404c-.198-.144-.265-.26-.282-.322a.437.437 0 0 0-.007-.02V8.983l.01-.338 3.617 1.605a.791.791 0 0 0 .645 0l3.6-1.598z" fill-rule="evenodd"/> <path d="M13.307 1H11.5a.5.5 0 1 1 0-1h3a.499.499 0 0 1 .5.65V3.5a.5.5 0 1 1-1 0V1.72l-1.793 1.774a.5.5 0 0 1-.713-.701L13.307 1zM12 14V8a.5.5 0 1 1 1 0v6.5a.5.5 0 0 1-.5.5H.563a.5.5 0 0 1-.5-.5v-13a.5.5 0 0 1 .5-.5H8a.5.5 0 0 1 0 1H1v12h11zM4 6a.5.5 0 0 1 0-1h3a.5.5 0 0 1 0 1H4zm0 2.5a.5.5 0 0 1 0-1h5a.5.5 0 0 1 0 1H4zM4 11a.5.5 0 1 1 0-1h5a.5.5 0 1 1 0 1H4z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 470 B

View File

@ -0,0 +1,3 @@
<svg width={{size}} height={{size}} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 210 B

View File

@ -5,15 +5,16 @@
Control Groups Control Groups
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#if model.canConfigure}}
{{#link-to 'vault.cluster.access.control-groups-configure' class="button has-icon-right is-ghost is-compact"}}
Configure
<ICon @glyph="chevron-right" @size=11 />
{{/link-to}}
{{/if}}
</p.levelRight>
</PageHeader> </PageHeader>
{{#if model.canConfigure}}
<Toolbar>
<ToolbarActions>
<ToolbarLink @params={{array 'vault.cluster.access.control-groups-configure'}}>
Configure
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{/if}}
<ControlGroup @model={{model}} /> <ControlGroup @model={{model}} />
{{else}} {{else}}
<UpgradePage @title="Control Groups" @minimumEdition="Vault Enterprise Premium" /> <UpgradePage @title="Control Groups" @minimumEdition="Vault Enterprise Premium" />

View File

@ -5,15 +5,16 @@
Control Groups Control Groups
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#if model.canConfigure}}
{{#link-to 'vault.cluster.access.control-groups-configure' class="button has-icon-right is-ghost is-compact"}}
Configure
<ICon @glyph="chevron-right" @size=11 />
{{/link-to}}
{{/if}}
</p.levelRight>
</PageHeader> </PageHeader>
{{#if model.canConfigure}}
<Toolbar>
<ToolbarActions>
<ToolbarLink @params={{array 'vault.cluster.access.control-groups-configure'}}>
Configure
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{/if}}
<form {{action (nav-to-route 'vault.cluster.access.control-group-accessor' model.id) on="submit"}}> <form {{action (nav-to-route 'vault.cluster.access.control-group-accessor' model.id) on="submit"}}>
<div class="box is-sideless is-fullwidth is-marginless"> <div class="box is-sideless is-fullwidth is-marginless">
<p class="has-text-grey is-size-8"> <p class="has-text-grey is-size-8">

View File

@ -16,14 +16,8 @@
{{model.name}} {{model.name}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#link-to "vault.cluster.access.identity.aliases.edit" model.id class="button has-icon-right is-ghost is-compact" data-test-alias-edit-link=true}}
Edit {{lowercase (humanize model.identityType)}}
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
<div class="box is-sideless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs sub-nav"> <nav class="tabs sub-nav">
<ul> <ul>
{{#each (tabs-for-identity-show model.identityType) as |tab|}} {{#each (tabs-for-identity-show model.identityType) as |tab|}}
@ -36,4 +30,14 @@
</ul> </ul>
</nav> </nav>
</div> </div>
<Toolbar>
<ToolbarActions>
<ToolbarLink
@params={{array "vault.cluster.access.identity.aliases.edit" model.id}}
@data-test-alias-edit-link=true
>
Edit {{lowercase (humanize model.identityType)}}
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{component (concat 'identity/item-alias/alias-' section) model=model}} {{component (concat 'identity/item-alias/alias-' section) model=model}}

View File

@ -16,20 +16,8 @@
{{model.name}} {{model.name}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#unless (or (and (eq model.identityType "group") (eq model.type "internal")) model.alias)}}
{{#link-to "vault.cluster.access.identity.aliases.add" (pluralize model.identityType) model.id class="button has-icon-right is-ghost is-compact" data-test-entity-create-link=true}}
Create alias
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
{{/unless}}
{{#link-to "vault.cluster.access.identity.edit" (pluralize model.identityType) model.id class="button has-icon-right is-ghost is-compact" data-test-entity-edit-link=true}}
Edit {{model.identityType}}
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
<div class="box is-sideless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs sub-nav"> <nav class="tabs sub-nav">
<ul> <ul>
{{#each (tabs-for-identity-show model.identityType model.type) as |tab|}} {{#each (tabs-for-identity-show model.identityType model.type) as |tab|}}
@ -42,4 +30,23 @@
</ul> </ul>
</nav> </nav>
</div> </div>
<Toolbar>
<ToolbarActions>
{{#unless (or (and (eq model.identityType "group") (eq model.type "internal")) model.alias)}}
<ToolbarLink
@type="add"
@params={{array "vault.cluster.access.identity.aliases.add" (pluralize model.identityType) model.id}}
@data-test-entity-create-link=true
>
Add alias
</ToolbarLink>
{{/unless}}
<ToolbarLink
@params={{array "vault.cluster.access.identity.edit" (pluralize model.identityType) model.id}}
@data-test-entity-edit-link=true
>
Edit {{model.identityType}}
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{component (concat 'identity/item-' section) model=model}} {{component (concat 'identity/item-' section) model=model}}

View File

@ -15,8 +15,39 @@
{{/link-to}} {{/link-to}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight> </PageHeader>
<div class="field is-grouped">
<Toolbar>
<ToolbarFilters>
{{navigate-input
filterFocusDidChange=(action "setFilterFocus")
filterDidChange=(action "setFilter")
filter=filter
filterMatchesKey=filterMatchesKey
firstPartialMatch=firstPartialMatch
baseKey=(get baseKey "id")
shouldNavigateTree=true
mode='leases'
placeholder='Filter leases'
}}
{{#if filterFocused}}
&nbsp;
&nbsp;
{{#if filterMatchesKey}}
{{#unless filterIsFolder}}
<p class="help has-text-grey is-size-8">
<kbd>ENTER</kbd> to go to see details
</p>
{{/unless}}
{{/if}}
{{#if firstPartialMatch}}
<p class="help has-text-grey is-size-8">
<kbd>TAB</kbd> to complete
</p>
{{/if}}
{{/if}}
</ToolbarFilters>
<ToolbarActions>
{{#if (not-eq baseKey.id '')}} {{#if (not-eq baseKey.id '')}}
<div class="control"> <div class="control">
{{#if (and capabilities.forceRevokePrefix.canUpdate (not confirmingRevoke))}} {{#if (and capabilities.forceRevokePrefix.canUpdate (not confirmingRevoke))}}
@ -56,42 +87,8 @@
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
</div> </ToolbarActions>
</p.levelRight> </Toolbar>
</PageHeader>
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless">
<div class="level">
<div class="level-left">
{{navigate-input
filterFocusDidChange=(action "setFilterFocus")
filterDidChange=(action "setFilter")
filter=filter
filterMatchesKey=filterMatchesKey
firstPartialMatch=firstPartialMatch
baseKey=(get baseKey "id")
shouldNavigateTree=true
mode='leases'
placeholder='Filter leases'
}}
{{#if filterFocused}}
&nbsp;
&nbsp;
{{#if filterMatchesKey}}
{{#unless filterIsFolder}}
<p class="help has-text-grey is-size-8">
<kbd>ENTER</kbd> to go to see details
</p>
{{/unless}}
{{/if}}
{{#if firstPartialMatch}}
<p class="help has-text-grey is-size-8">
<kbd>TAB</kbd> to complete
</p>
{{/if}}
{{/if}}
</div>
</div>
</div>
{{#if model.meta.total}} {{#if model.meta.total}}
{{#each model as |item|}} {{#each model as |item|}}

View File

@ -12,25 +12,21 @@
{{capitalize model.methodType}} {{capitalize model.methodType}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#if (eq section "configuration")}}
<div class="field is-grouped">
<div class="control">
{{#link-to
"vault.cluster.settings.auth.configure"
model.id
class="button is-ghost has-icon-right is-compact"
data-test-configure-link=true
}}
Configure
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</div>
</div>
{{/if}}
</p.levelRight>
</PageHeader> </PageHeader>
{{section-tabs model 'authShow'}} {{section-tabs model 'authShow'}}
{{component (concat "auth-method/" section) model=model}}
{{#if (eq section "configuration")}}
<Toolbar>
<ToolbarActions>
<ToolbarLink
@params={{array "vault.cluster.settings.auth.configure" model.id}}
@data-test-configure-link=true
>
Configure
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{/if}}
{{component (concat "auth-method/" section) model=model}}

View File

@ -4,14 +4,19 @@
Authentication Methods Authentication Methods
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#link-to 'vault.cluster.settings.auth.enable' class="button has-icon-right is-ghost is-compact"}}
Enable new method
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
<Toolbar>
<ToolbarActions>
<ToolbarLink
@type="add"
@params={{array 'vault.cluster.settings.auth.enable'}}
>
Enable new method
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{#each (sort-by "path" model) as |method|}} {{#each (sort-by "path" model) as |method|}}
<div <div
class="list-item-row" class="list-item-row"

View File

@ -5,13 +5,19 @@
Namespaces Namespaces
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#link-to 'vault.cluster.access.namespaces.create' class="button has-icon-right is-ghost is-compact"}}
Create a Namespace
<ICon @glyph="chevron-right" @size=11 />
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
<Toolbar>
<ToolbarActions>
<ToolbarLink
@type="add"
@params={{array 'vault.cluster.access.namespaces.create'}}
>
Create namespace
</ToolbarLink>
</ToolbarActions>
</Toolbar>
<ListView @items={{model}} @itemNoun="namespace" @emptyActions="empty-action-namespaces" as |list|> <ListView @items={{model}} @itemNoun="namespace" @emptyActions="empty-action-namespaces" as |list|>
<ListItem as |Item|> <ListItem as |Item|>
<Item.content> <Item.content>

View File

@ -6,6 +6,7 @@
</Page.header> </Page.header>
{{#if (has-feature "Namespaces")}} {{#if (has-feature "Namespaces")}}
<Page.sub-header> <Page.sub-header>
<Toolbar class="toolbar-namespace-picker">
<div class="field is-horizontal"> <div class="field is-horizontal">
<div class="field-label is-normal"> <div class="field-label is-normal">
<label class="is-label" for="namespace">Namespace</label> <label class="is-label" for="namespace">Namespace</label>
@ -27,6 +28,7 @@
</div> </div>
</div> </div>
</div> </div>
</Toolbar>
</Page.sub-header> </Page.sub-header>
{{/if}} {{/if}}
<Page.content> <Page.content>

View File

@ -22,7 +22,7 @@
<label for="policy-name" class="is-label">Name</label> <label for="policy-name" class="is-label">Name</label>
<div class="control"> <div class="control">
<input <input
type="text"nn type="text"
id="policy-name" id="policy-name"
class="input" class="input"
value={{model.name}} value={{model.name}}

View File

@ -10,17 +10,10 @@
{{/unless}} {{/unless}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#link-to "vault.cluster.policies.create" class="button has-icon-right is-ghost is-compact" data-test-policy-create-link=true}}
Create {{uppercase policyType}} policy
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
{{#if model.meta.total}} {{#if model.meta.total}}
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless"> <Toolbar>
<div class="level"> <ToolbarFilters>
<div class="level-left">
{{navigate-input {{navigate-input
filterFocusDidChange=(action "setFilterFocus") filterFocusDidChange=(action "setFilterFocus")
filterDidChange=(action "setFilter") filterDidChange=(action "setFilter")
@ -43,9 +36,17 @@
</p> </p>
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </ToolbarFilters>
</div> <ToolbarActions>
</div> <ToolbarLink
@type="add"
@params={{array 'vault.cluster.policies.create'}}
@data-test-policy-create-link=true
>
Create {{uppercase policyType}} policy
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{#each model as |item|}} {{#each model as |item|}}
{{#if (eq item.id "root")}} {{#if (eq item.id "root")}}
<div class="list-item-row is-flex" data-test-policy-item> <div class="list-item-row is-flex" data-test-policy-item>

View File

@ -20,33 +20,35 @@
</h1> </h1>
</p.levelLeft> </p.levelLeft>
</PageHeader> </PageHeader>
{{#if (and (not-eq model.id "root") (or capabilities.canUpdate capabilities.canDelete))}}
<Toolbar>
<ToolbarActions>
<ToolbarLink
@params={{array 'vault.cluster.policy.show' model.id}}
@data-test-policy-edit-toggle=true
>
Back to policy
</ToolbarLink>
<div class="toolbar-separator" />
{{#if (and (not-eq model.id "default") capabilities.canDelete)}}
{{#confirm-action
buttonClasses="toolbar-link"
onConfirmAction=(action "deletePolicy" model)
confirmMessage=(concat "Are you sure you want to delete " model.id "?")
data-test-policy-delete=true
}}
Delete
<ICon @glyph="chevron-right" @size=12 />
{{/confirm-action}}
{{/if}}
</ToolbarActions>
</Toolbar>
{{/if}}
<form {{action "savePolicy" model on="submit"}}> <form {{action "savePolicy" model on="submit"}}>
<div class="box is-bottomless is-fullwidth is-marginless"> <div class="box is-bottomless is-fullwidth is-marginless">
{{message-error model=model}} {{message-error model=model}}
<NamespaceReminder @mode="edit" @noun="policy" /> <NamespaceReminder @mode="edit" @noun="policy" />
<div class="level is-mobile">
<div class="level-left">
<label for="policy" class="is-label">Policy</label> <label for="policy" class="is-label">Policy</label>
</div>
<div class="level-right">
<div class="field is-horizontal is-flex-end is-single-line">
{{#if (and (not-eq model.id "root") (or capabilities.canUpdate capabilities.canDelete))}}
<div class="control is-flex">
{{input
id="edit"
type="checkbox"
name="navToEdit"
class="switch is-rounded is-success is-small"
checked=true
change=(action (nav-to-route 'vault.cluster.policy.show' model.id replace=true) )
data-test-policy-edit-toggle=true
}}
<label for="edit">Edit</label>
</div>
{{/if}}
</div>
</div>
</div>
<div class="field"> <div class="field">
{{ivy-codemirror {{ivy-codemirror
value=model.policy value=model.policy
@ -90,16 +92,6 @@
{{/link-to}} {{/link-to}}
</div> </div>
</div> </div>
{{#if (and (not-eq model.id "default") capabilities.canDelete)}}
{{#confirm-action
buttonClasses="button is-ghost"
onConfirmAction=(action "deletePolicy" model)
confirmMessage=(concat "Are you sure you want to delete " model.id "?")
data-test-policy-delete=true
}}
Delete
{{/confirm-action}}
{{/if}}
</div> </div>
</div> </div>
</form> </form>

View File

@ -20,34 +20,35 @@
</h1> </h1>
</p.levelLeft> </p.levelLeft>
</PageHeader> </PageHeader>
<div class="box is-bottomless is-fullwidth is-marginless"> <Toolbar>
<div class="level is-mobile"> <ToolbarActions>
<div class="level-left"> <ToolbarDownloadButton
<label for="policy" class="is-label">Policy</label> @classNames="toolbar-link"
{{#if (eq policyType "acl")}} @actionText="Download policy"
<span class="tag is-white is-size-9" data-test-acl-format>({{uppercase model.format}} format)</span> @extension={{if (eq policyType "acl") model.format "sentinel"}}
{{/if}} @filename=model.name
</div> @data=model.policy
<div class="level-right"> />
<div class="field is-horizontal is-flex-end is-single-line">
{{#if (and (not-eq model.id "root") (or capabilities.canUpdate capabilities.canDelete))}} {{#if (and (not-eq model.id "root") (or capabilities.canUpdate capabilities.canDelete))}}
<div class="control is-flex"> <ToolbarLink
{{input @params={{array 'vault.cluster.policy.edit' model.id}}
id="edit" @data-test-policy-edit-toggle=true
type="checkbox" >
name="navToEdit" Edit policy
class="switch is-rounded is-success is-small" </ToolbarLink>
checked=false
change=(action (nav-to-route 'vault.cluster.policy.edit' model.id replace=true) )
data-test-policy-edit-toggle=true
}}
<label for="edit">Edit</label>
</div>
{{/if}} {{/if}}
</div> </ToolbarActions>
</div> </Toolbar>
</div> <div class="box is-bottomless is-fullwidth is-marginless">
<div class="field"> <div class="field">
<label for="policy" class="is-label">
Policy
{{#if (eq policyType "acl")}}
<span class="tag is-white is-size-9 has-text-grey" data-test-acl-format>
({{uppercase model.format}} format)
</span>
{{/if}}
</label>
{{ivy-codemirror {{ivy-codemirror
value=model.policy value=model.policy
options=(hash options=(hash
@ -71,13 +72,4 @@
</ul> </ul>
</div> </div>
{{/if}} {{/if}}
<div class="field box is-shadowless no-bottom-padding is-marginless">
{{download-button
classNames="link is-pulled-right"
actionText="Download policy"
extension=(if (eq policyType "acl") model.format "sentinel")
filename=model.name
data=model.policy
}}
</div>
</div> </div>

View File

@ -25,7 +25,7 @@
</h1> </h1>
</p.levelLeft> </p.levelLeft>
</PageHeader> </PageHeader>
<div class="box is-bottomless is-fullwidth is-paddingless is-marginless"> <div class="tabs-container box is-bottomless is-fullwidth is-paddingless is-marginless">
<nav class="tabs sub-nav"> <nav class="tabs sub-nav">
<ul> <ul>
<li class="{{if (is-active-route 'vault.cluster.replication.mode.index') 'is-active' ''}}"> <li class="{{if (is-active-route 'vault.cluster.replication.mode.index') 'is-active' ''}}">

View File

@ -33,6 +33,7 @@
data-test-delete-mount-config=true data-test-delete-mount-config=true
}} }}
Delete Delete
<ICon @glyph="chevron-right" @size=12 />
{{/confirm-action}} {{/confirm-action}}
</div> </div>
</form> </form>

View File

@ -1,4 +1,26 @@
{{#if model.replicationAttrs.isPrimary}} {{#if model.replicationAttrs.isPrimary}}
<Toolbar>
<ToolbarActions>
{{#if model.replicationAttrs.knownSecondaries.length}}
{{#if model.canRevokeSecondary}}
<ToolbarLink
@params={{array 'vault.cluster.replication.mode.secondaries.revoke' model.name replicationMode}}
>
Revoke secondary
</ToolbarLink>
{{/if}}
{{/if}}
{{#if model.canAddSecondary}}
<ToolbarLink
@type="add"
@params={{array 'vault.cluster.replication.mode.secondaries.add' model.name replicationMode}}
@data-test-secondary-add=true
>
Add secondary
</ToolbarLink>
{{/if}}
</ToolbarActions>
</Toolbar>
{{#if model.replicationAttrs.knownSecondaries.length}} {{#if model.replicationAttrs.knownSecondaries.length}}
{{#each model.replicationAttrs.knownSecondaries as |secondary|}} {{#each model.replicationAttrs.knownSecondaries as |secondary|}}
<div class="box is-shadowless is-marginless" data-test-secondary-name={{secondary}}> <div class="box is-shadowless is-marginless" data-test-secondary-name={{secondary}}>
@ -60,20 +82,4 @@
</DocLink> </DocLink>
</EmptyState> </EmptyState>
{{/if}} {{/if}}
<div class="field is-grouped box is-shadowless is-fullwidth">
{{#if model.canAddSecondary}}
<div class="control">
{{#link-to 'vault.cluster.replication.mode.secondaries.add' model.name replicationMode class="button" data-test-secondary-add=true }}
Add
{{/link-to}}
</div>
{{/if}}
{{#if model.canRevokeSecondary}}
<div class="control">
{{#link-to 'vault.cluster.replication.mode.secondaries.revoke' model.name replicationMode class="button"}}
Revoke
{{/link-to}}
</div>
{{/if}}
</div>
{{/if}} {{/if}}

View File

@ -1,4 +1,21 @@
{{secret-list-header model=model isConfigure=true backendCrumb=(hash label=model.id text=model.id path="vault.cluster.secrets.backend.list-root" model=model.id)}} <SecretListHeader
@model={{model}}
@backendCrumb={{hash label=model.id text=model.id path="vault.cluster.secrets.backend.list-root" model=model.id}}
@isConfigure=true
/>
{{#if isConfigurable}}
<Toolbar>
<ToolbarActions>
<ToolbarLink
@params={{array 'vault.cluster.settings.configure-secret-backend' model.id}}
@data-test-secret-backend-configure=true
>
Configure
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{/if}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless"> <div class="box is-fullwidth is-sideless is-paddingless is-marginless">
{{#each model.attrs as |attr|}} {{#each model.attrs as |attr|}}

View File

@ -1,10 +1,16 @@
{{secret-list-header isCertTab=(eq tab "certs") model=backendModel baseKey=baseKey backendCrumb=backendCrumb filter=filter}} <SecretListHeader
@isCertTab={{eq tab "certs"}}
@model={{backendModel}}
@baseKey={{baseKey}}
@backendCrumb={{backendCrumb}}
@filter={{filter}}
/>
{{#with (options-for-backend backendType tab) as |options|}} {{#with (options-for-backend backendType tab) as |options|}}
{{#if (or model.meta.total (not isConfigurableTab))}}
<Toolbar>
{{#if model.meta.total}} {{#if model.meta.total}}
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless"> <ToolbarFilters>
<div class="level">
<div class="level-left">
{{navigate-input {{navigate-input
enterpriseProduct="vault" enterpriseProduct="vault"
filterFocusDidChange=(action "setFilterFocus") filterFocusDidChange=(action "setFilterFocus")
@ -32,9 +38,24 @@
</p> </p>
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </ToolbarFilters>
</div> {{/if}}
</div>
<ToolbarActions>
<ToolbarSecretLink
@secret=''
@mode="create"
@type="add"
@queryParams={{query-params initialKey=(or filter baseKey.id)}}
@data-test-secret-create=true
>
{{options.create}}
</ToolbarSecretLink>
</ToolbarActions>
</Toolbar>
{{/if}}
{{#if model.meta.total}}
{{#each model as |item|}} {{#each model as |item|}}
{{partial options.listItemPartial}} {{partial options.listItemPartial}}
{{else}} {{else}}

View File

@ -30,23 +30,25 @@
{{model.id}} {{model.id}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#secret-link
mode="show"
secret=model.id
class="button has-icon-right is-ghost is-compact"
}}
Details
{{i-con glyph="chevron-right" size=11}}
{{/secret-link}}
</p.levelRight>
</PageHeader> </PageHeader>
{{transit-key-actions
selectedAction=selectedAction <Toolbar>
backend=backend <ToolbarActions>
key=model <ToolbarSecretLink
capabilities=capabilities @secret={{model.id}}
onRefresh=(action "refresh") @mode="show"
}} >
Details
</ToolbarSecretLink>
</ToolbarActions>
</Toolbar>
<TransitKeyActions
@selectedAction={{selectedAction}}
@backend={{backend}}
@key={{model}}
@capabilities={{capabilities}}
@onRefresh={{action "refresh"}}
/>
</div> </div>
</div> </div>

View File

@ -4,14 +4,19 @@
Secrets Engines Secrets Engines
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
{{#link-to 'vault.cluster.settings.mount-secret-backend' class="button has-icon-right is-ghost is-compact"}}
Enable new engine
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</p.levelRight>
</PageHeader> </PageHeader>
<Toolbar>
<ToolbarActions>
<ToolbarLink
@type="add"
@params={{array 'vault.cluster.settings.mount-secret-backend'}}
>
Enable new engine
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{#each supportedBackends as |backend|}} {{#each supportedBackends as |backend|}}
{{#linked-block {{#linked-block
"vault.cluster.secrets.backend.list-root" "vault.cluster.secrets.backend.list-root"

View File

@ -12,22 +12,19 @@
Configure {{get (find-by "type" model.type (mountable-auth-methods)) "displayName"}} Configure {{get (find-by "type" model.type (mountable-auth-methods)) "displayName"}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
<div class="field is-grouped">
<div class="control">
{{#link-to
"vault.cluster.access.method"
model.id
class="button is-ghost has-icon-right is-compact"
data-test-backend-view-link=true
}}
View method
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</div>
</div>
</p.levelRight>
</PageHeader> </PageHeader>
{{section-tabs model}} {{section-tabs model}}
<Toolbar>
<ToolbarActions>
<ToolbarLink
@params={{array "vault.cluster.access.method" model.id}}
@data-test-backend-view-link=true
>
View method
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{outlet}} {{outlet}}

View File

@ -12,22 +12,18 @@
Configure {{get (options-for-backend model.type) "displayName"}} Configure {{get (options-for-backend model.type) "displayName"}}
</h1> </h1>
</p.levelLeft> </p.levelLeft>
<p.levelRight>
<div class="field is-grouped">
<div class="control">
{{#link-to
"vault.cluster.secrets.backend"
model.id
class="button has-icon-right is-ghost is-compact"
data-test-backend-view-link=true
}}
View backend
{{i-con glyph="chevron-right" size=11}}
{{/link-to}}
</div>
</div>
</p.levelRight>
</PageHeader> </PageHeader>
<Toolbar>
<ToolbarActions>
<ToolbarLink
@params={{array "vault.cluster.secrets.backend" model.id}}
@data-test-backend-view-link=true
>
View backend
</ToolbarLink>
</ToolbarActions>
</Toolbar>
{{partial (concat "partials/secret-backend-settings/" model.type)}} {{partial (concat "partials/secret-backend-settings/" model.type)}}
{{outlet}} {{outlet}}

View File

@ -33,6 +33,7 @@ module('Acceptance | aws secret backend', function(hooks) {
await enablePage.enable('aws', path); await enablePage.enable('aws', path);
await click('[data-test-configuration-tab]');
await click('[data-test-secret-backend-configure]'); await click('[data-test-secret-backend-configure]');
assert.equal(currentURL(), `/vault/settings/secrets/configure/${path}`); assert.equal(currentURL(), `/vault/settings/secrets/configure/${path}`);
assert.ok(findAll('[data-test-aws-root-creds-form]').length, 'renders the empty root creds form'); assert.ok(findAll('[data-test-aws-root-creds-form]').length, 'renders the empty root creds form');

View File

@ -1,4 +1,4 @@
import { currentRouteName, settled } from '@ember/test-helpers'; import { click, currentRouteName, settled } from '@ember/test-helpers';
import { module, test } from 'qunit'; import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit'; import { setupApplicationTest } from 'ember-qunit';
import page from 'vault/tests/pages/secrets/backend/list'; import page from 'vault/tests/pages/secrets/backend/list';
@ -22,6 +22,7 @@ module('Acceptance | secrets/pki/list', function(hooks) {
await mountAndNav(assert); await mountAndNav(assert);
assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.list-root', 'redirects from the index'); assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.list-root', 'redirects from the index');
assert.ok(page.createIsPresent, 'create button is present'); assert.ok(page.createIsPresent, 'create button is present');
await click('[data-test-configuration-tab]');
assert.ok(page.configureIsPresent, 'configure button is present'); assert.ok(page.configureIsPresent, 'configure button is present');
assert.equal(page.tabs.length, 2, 'shows 2 tabs'); assert.equal(page.tabs.length, 2, 'shows 2 tabs');
assert.ok(page.backendIsEmpty); assert.ok(page.backendIsEmpty);
@ -35,6 +36,7 @@ module('Acceptance | secrets/pki/list', function(hooks) {
test('it navigates to the configure page', async function(assert) { test('it navigates to the configure page', async function(assert) {
await mountAndNav(assert); await mountAndNav(assert);
await click('[data-test-configuration-tab]');
await page.configure(); await page.configure();
await settled(); await settled();
assert.equal( assert.equal(

View File

@ -63,6 +63,7 @@ module('Acceptance | ssh secret backend', function(hooks) {
const sshPath = `ssh-${now}`; const sshPath = `ssh-${now}`;
await enablePage.enable('ssh', sshPath); await enablePage.enable('ssh', sshPath);
await click('[data-test-configuration-tab]');
await click('[data-test-secret-backend-configure]'); await click('[data-test-secret-backend-configure]');
assert.equal(currentURL(), `/vault/settings/secrets/configure/${sshPath}`); assert.equal(currentURL(), `/vault/settings/secrets/configure/${sshPath}`);
assert.ok(findAll('[data-test-ssh-configure-form]').length, 'renders the empty configuration form'); assert.ok(findAll('[data-test-ssh-configure-form]').length, 'renders the empty configuration form');

View File

@ -51,8 +51,6 @@ const OIDC_AUTH_RESPONSE = {
}, },
}; };
const WAIT_TIME = 50;
const routerStub = Service.extend({ const routerStub = Service.extend({
urlFor() { urlFor() {
return 'http://example.com'; return 'http://example.com';

View File

@ -0,0 +1,15 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | toolbar-actions', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<ToolbarActions>These are the toolbar actions</ToolbarActions>`);
assert.equal(this.element.textContent.trim(), 'These are the toolbar actions');
assert.dom('.toolbar-actions').exists();
});
});

View File

@ -0,0 +1,17 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { isPresent } from 'ember-cli-page-object';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | toolbar-download-button', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<ToolbarDownloadButton @actionText="Link" />`);
assert.equal(this.element.textContent.trim(), 'Link');
assert.ok(isPresent('.toolbar-link'));
assert.ok(isPresent('.icon'));
});
});

View File

@ -0,0 +1,16 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { isPresent } from 'ember-cli-page-object';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | toolbar-filters', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<ToolbarFilters>These are the toolbar filters</ToolbarFilters>`);
assert.equal(this.element.textContent.trim(), 'These are the toolbar filters');
assert.ok(isPresent('.toolbar-filters'));
});
});

View File

@ -0,0 +1,17 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { isPresent } from 'ember-cli-page-object';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | toolbar-link', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<ToolbarLink @params="/secrets">Link</ToolbarLink>`);
assert.equal(this.element.textContent.trim(), 'Link');
assert.ok(isPresent('.toolbar-link'));
assert.ok(isPresent('.icon'));
});
});

View File

@ -0,0 +1,17 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { isPresent } from 'ember-cli-page-object';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | toolbar', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
await render(hbs`<Toolbar>This is the toolbar content</Toolbar>`);
assert.equal(this.element.textContent.trim(), 'This is the toolbar content');
assert.ok(isPresent('.toolbar'));
assert.ok(isPresent('.toolbar-scroller'));
});
});