Merge pull request #5758 from hashicorp/ui-empty-states

UI: Empty state styles
This commit is contained in:
Joshua Ogle 2018-11-16 08:58:26 -07:00 committed by GitHub
commit 194c90a01d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 417 additions and 343 deletions

View File

@ -11,9 +11,10 @@ export default Component.extend({
target: '_blank',
rel: 'noreferrer noopener',
host: 'https://www.vaultproject.io',
path: '/',
href: computed('path', function() {
return `https://www.vaultproject.io${this.get('path')}`;
href: computed('host', 'path', function() {
return `${this.host}${this.path}`;
}),
});

View File

@ -0,0 +1,6 @@
import OuterHTML from './outer-html';
export default OuterHTML.extend({
title: null,
message: null,
});

View File

@ -0,0 +1,5 @@
import DocLink from './doc-link';
export default DocLink.extend({
host: 'https://learn.hashicorp.com',
});

View File

@ -6,9 +6,17 @@ export default Component.extend({
tagName: '',
items: null,
itemNoun: 'item',
// the dasherized name of a component to render
// in the EmptyState component if there are no items in items.length
emptyActions: '',
emptyTitle: computed('itemNoun', function() {
let items = pluralize(this.get('itemNoun'));
return `No ${items} yet`;
}),
emptyMessage: computed('itemNoun', function() {
let items = pluralize(this.get('itemNoun'));
return `There are currently no ${items}`;
return `Your ${items} will be listed here. Add your first ${this.get('itemNoun')} to get started.`;
}),
});

View File

@ -49,6 +49,21 @@ export default Controller.extend({
return !!utils.keyIsFolder(this.get('filter'));
}),
emptyTitle: computed('baseKey.id', 'filter', 'filterIsFolder', function() {
let id = this.get('baseKey.id');
let filter = this.filter;
if (id === '') {
return 'There are currently no leases.';
}
if (this.filterIsFolder) {
if (filter === id) {
return `There are no leases under "${filter}".`;
} else {
return `We couldn't find a prefix matching "${filter}".`;
}
}
}),
actions: {
setFilter(val) {
this.set('filter', val);

View File

@ -0,0 +1,38 @@
.empty-state {
align-items: center;
color: $grey;
display: flex;
background: $ui-gray-050;
justify-content: center;
padding: $spacing-xxl $spacing-s;
box-shadow: 0 -2px 0 -1px $ui-gray-300;
}
.empty-state-content {
max-width: 320px;
}
.empty-state-title {
color: $grey;
font-size: $size-4;
font-weight: $font-weight-semibold;
line-height: 1.2;
margin-bottom: $spacing-xs;
}
.empty-state-actions {
margin-top: $spacing-xs;
a,
.link,
a:not(.button):not(.file-delete-button):not(.tag) {
color: $blue;
font-size: $size-8;
font-weight: $font-weight-semibold;
text-decoration: none;
}
> * + * {
margin-left: $spacing-s;
}
}

View File

@ -49,6 +49,7 @@
@import "./components/console-ui-panel";
@import "./components/control-group";
@import "./components/doc-link";
@import "./components/empty-state";
@import "./components/env-banner";
@import "./components/features-selection";
@import "./components/form-section";

View File

@ -21,7 +21,7 @@ $ui-gray-050: #F7F8FA;
$ui-gray-100: #EBEEF2;
$ui-gray-200: #DCE0E6;
$ui-gray-300: #BAC1CC;
$ui-gray-500: #6a7786;
$ui-gray-500: #6F7682;
$ui-gray-700: #525761;
$ui-gray-800: #373A42;
$ui-gray-900: #1F2124;

View File

@ -1,11 +0,0 @@
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
{{yield}}
</p>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,7 @@
{{#link-to "vault.cluster.access.namespaces.create"}}
Create namespace
{{/link-to}}
<LearnLink @path="/vault/security/namespaces">
Learn More
</LearnLink>

View File

@ -0,0 +1,21 @@
<div class="empty-state">
<div class="empty-state-content">
<h3 class="empty-state-title">
{{title}}
</h3>
{{#if message}}
<p class="empty-state-message">
{{message}}
</p>
{{/if}}
{{#if hasBlock}}
<div class="empty-state-actions">
{{yield}}
</div>
{{else if emptyActions}}
<div class="empty-state-actions">
{{component emptyActions}}
</div>
{{/if}}
</div>
</div>

View File

@ -33,10 +33,12 @@
</ul>
</nav>
</div>
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless">
<div class="level">
<div class="level-left">
{{identity/lookup-input type=identityType}}
{{#if model.meta.total}}
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless">
<div class="level">
<div class="level-left">
{{identity/lookup-input type=identityType}}
</div>
</div>
</div>
</div>
{{/if}}

View File

@ -17,15 +17,15 @@
</div>
</div>
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
There is no metadata associated with {{model.name}}.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="No metadata for {{model.name}} yet"
@message="You can store custom data that you want to associate with a {{lowercase (humanize model.identityType)}}. Edit this {{lowercase (humanize model.identityType)}} to get started."
>
{{#link-to "vault.cluster.access.identity.aliases.edit" model.id tagName="button" class="link"}}
Edit {{lowercase (humanize model.identityType)}}
{{/link-to}}
<LearnLink @path="/vault/identity-access-management/iam-identity">
Learn More
</LearnLink>
</EmptyState>
{{/each-in}}

View File

@ -28,15 +28,7 @@
</div>
{{/linked-block}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey" data-test-no-entity-aliases-text>
There are no {{model.identityType}} aliases for {{model.name}}.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="No {{model.identityType}} aliases for {{model.name}} yet"
/>
{{/each}}

View File

@ -25,15 +25,7 @@
{{/linked-block}}
{{/each}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
{{model.name}} is not a member of any groups.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="{{model.name}} is not a member of any groups."
/>
{{/if}}

View File

@ -52,15 +52,7 @@
{{/linked-block}}
{{/each}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
There are no members in this group.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="No members in this group yet"
/>
{{/if}}

View File

@ -14,15 +14,7 @@
</div>
</div>
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
There is no metadata associated with {{model.name}}.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="No metadata associated with {{model.name}} yet"
/>
{{/each-in}}

View File

@ -23,15 +23,7 @@
{{/linked-block}}
{{/each}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
This group has no parent groups.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="This group has no parent groups yet"
/>
{{/if}}

View File

@ -20,15 +20,7 @@
</div>
{{/linked-block}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey" data-test-no-entity-aliases-text>
There are no policies associated with {{model.name}}.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="No policies associated with {{model.name}} yet"
/>
{{/each}}

View File

@ -5,15 +5,9 @@
{{/each}}
</div>
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
{{emptyMessage}}
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title={{this.emptyTitle}}
@message={{this.emptyMessage}}
@emptyActions={{this.emptyActions}}
/>
{{/if}}

View File

@ -1,11 +1,22 @@
{{#if (and isV2 modelForData.destroyed)}}
<BlockEmpty>
Version {{modelForData.version}} of this secret has been permanently destroyed.
</BlockEmpty>
<EmptyState
@title="Version {{modelForData.version}} of this secret has been permanently destroyed"
@message="A version that has been permanently deleted cannot be restored. You can see other versions of this secret in the History menu."
>
<DocLink @path="/docs/secrets/kv/kv-v2.html">
Learn More
</DocLink>
</EmptyState>
{{else if (and isV2 modelForData.deleted)}}
<BlockEmpty>
Version {{modelForData.version}} of this secret has been deleted.
</BlockEmpty>
<EmptyState
@title="Version {{modelForData.version}} of this secret has been deleted"
@message="A version that has been deleted but can be undeleted using the Version {{modelForData.version}} menu above.
You can also see other versions of this secret in the History menu."
>
<DocLink @path="/docs/secrets/kv/kv-v2.html">
Learn More
</DocLink>
</EmptyState>
{{else}}
{{#if showAdvancedMode}}
{{json-editor

View File

@ -1,4 +1,4 @@
{{identity/entity-nav identityType=identityType}}
{{identity/entity-nav identityType=identityType model=model}}
{{#if model.meta.total}}
{{#each model as |item|}}
{{#linked-block
@ -35,23 +35,23 @@
</div>
{{/linked-block}}
{{/each}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link="vault.cluster.access.identity.aliases.index"
}}
{{/if}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
There are currently no {{identityType}} aliases.
</p>
</div>
</div>
</div>
</div>
{{/if}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link="vault.cluster.access.identity.aliases.index"
}}
<EmptyState
@title="No {{identityType}} aliases yet"
@message="A list of {{identityType}} aliases in this namespace will be listed here. Choose one of the {{pluralize identityType}} and click &quot;Create Alias&quot; to get started."
>
{{#link-to "vault.cluster.access.identity.create" (pluralize identityType) tagName="button" class="link"}}
Create {{identityType}}
{{/link-to}}
<LearnLink @path="/vault/identity-access-management/iam-identity">
Learn More
</LearnLink>
</EmptyState>
{{/if}}

View File

@ -1,4 +1,4 @@
{{identity/entity-nav identityType=identityType}}
{{identity/entity-nav identityType=identityType model=model}}
{{#if model.meta.total}}
{{#each model as |item|}}
{{#linked-block
@ -57,7 +57,7 @@
<button type="button" {{action "toggleDisabled" item}} class="link">
Enable
</button>
{{else}}
{{else if (eq identityType 'entity')}}
{{#confirm-action
confirmButtonClasses="button is-primary"
confirmButtonText="Disable"
@ -77,7 +77,7 @@
{{#if item.canAddAlias}}
<li class="action">
{{#link-to "vault.cluster.access.identity.aliases.add" (pluralize identityType) item.id}}
Add alias
Create alias
{{/link-to}}
</li>
{{/if}}
@ -106,23 +106,23 @@
</div>
{{/linked-block}}
{{/each}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link="vault.cluster.access.identity.index"
}}
{{/if}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
There are currently no {{pluralize identityType}}.
</p>
</div>
</div>
</div>
</div>
{{/if}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link="vault.cluster.access.identity.index"
}}
<EmptyState
@title="No {{pluralize identityType}} yet"
@message="A list of {{pluralize identityType}} in this namespace will be listed here. Create your first {{identityType}} to get started."
>
{{#link-to "vault.cluster.access.identity.create" (pluralize identityType) tagName="button" class="link"}}
Create {{identityType}}
{{/link-to}}
<LearnLink @path="/vault/identity-access-management/iam-identity">
Learn More
</LearnLink>
</EmptyState>
{{/if}}

View File

@ -32,7 +32,7 @@
<div class="box is-sideless is-fullwidth is-paddingless is-marginless">
<nav class="tabs sub-nav">
<ul>
{{#each (tabs-for-identity-show modennl.identityType model.type) as |tab|}}
{{#each (tabs-for-identity-show model.identityType model.type) as |tab|}}
{{#link-to "vault.cluster.access.identity.show" (pluralize model.identityType) model.id tab tagName="li"}}
{{#link-to "vault.cluster.access.identity.show" (pluralize model.identityType) model.id tab}}
{{capitalize (humanize tab)}}

View File

@ -10,32 +10,34 @@
{{model.message}}
{{/unless}}
<div class="box is-sideless is-fullwidth is-marginless">
{{#if (eq model.httpStatus 400)}}
{{#if (eq model.httpStatus 400)}}
<AlertBanner
@type="danger"
@message="{{model.keyId}} is not a valid lease ID"
/>
{{else if (eq model.httpStatus 404)}}
<EmptyState
@title="No leases with that ID"
@message="Unable to find lease for the ID &quot;{{model.keyId}}&quot;. Try going back to the lookup and re-entering the ID."
>
{{#link-to "vault.cluster.access.leases" class="link"}}
Back to lookup
{{/link-to}}
</EmptyState>
{{else if (eq model.httpStatus 403)}}
<EmptyState
@title="You don't have access to a lease with that ID"
@message="If you think you've reached this page in error, please contact your administrator."
>
{{#link-to "vault.cluster.access.leases" class="link"}}
Back to lookup
{{/link-to}}
</EmptyState>
{{else}}
{{#each model.errors as |error|}}
<AlertBanner
@type="danger"
@message="{{model.keyId}} is not a valid lease ID"
@message={{error}}
/>
{{else if (eq model.httpStatus 404)}}
<p class="message">
Unable to find lease for the <code>id</code>: <code>{{model.keyId}}</code>. Try going back to the
{{#link-to "vault.cluster.access.leases"}}lookup{{/link-to}}
and re-entering the <code>id</code>.
</p>
{{else if (eq model.httpStatus 403)}}
<p class="message">
You don't have access to <code>{{model.keyId}}</code>. If you think you've reached this page in error, please contact your administrator.
</p>
{{else}}
{{#each model.errors as |error|}}
<p class="message">
{{error}}
</p>
{{/each}}
{{/if}}
</div>
<div class="field is-grouped box is-fullwidth is-bottomless">
{{#link-to "vault.cluster.access.leases" class="button"}}
Back
{{/link-to}}
</div>
{{/each}}
{{/if}}

View File

@ -104,38 +104,16 @@
glyph=(if item.isFolder 'folder' 'document')
size=14
class="has-text-grey-light"
}}
<span class="has-text-weight-semibold">
{{or item.keyWithoutParent item.id}}
</span>
{{/link-to}}
}}<span class="has-text-weight-semibold">{{or item.keyWithoutParent item.id}}</span>{{/link-to}}
{{else}}
<div class="box is-sideless">
There are no leases matching <code>{{filter}}</code>
</div>
<EmptyState
@title="There are no leases matching &quot;{{this.filter}}&quot;"
/>
{{/each}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
{{#if (eq baseKey.id '')}}
There are currently no leases.
{{else}}
{{#if filterIsFolder}}
{{#if (eq filter baseKey.id)}}
There are no leases under <code>{{filter}}</code>.
{{else}}
We couldn't find a prefix matching <code>{{filter}}</code>.
{{/if}}
{{/if}}
{{/if}}
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title={{this.emptyTitle}}
/>
{{/if}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination

View File

@ -7,12 +7,12 @@
</p.levelLeft>
<p.levelRight>
{{#link-to 'vault.cluster.access.namespaces.create' class="button has-icon-right is-ghost is-compact"}}
Create a namespace
Create namespace
<ICon @glyph="chevron-right" @size=11 />
{{/link-to}}
</p.levelRight>
</PageHeader>
<ListView @items={{model}} @itemNoun="namespace" as |list|>
<ListView @items={{model}} @itemNoun="namespace" @emptyActions="empty-action-namespaces" as |list|>
<ListItem as |Item|>
<Item.content>
{{list.item.id}}

View File

@ -17,35 +17,35 @@
{{/link-to}}
</p.levelRight>
</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
extraNavParams=policyType
placeholder="Filter policies"
mode="policy"
}}
{{#if filterFocused}}
{{#if filterMatchesKey}}
<p class="input-hint">
<kbd>ENTER</kbd> to go to <code>{{or pageFilter filter}}</code>
</p>
{{#if model.meta.total}}
<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
extraNavParams=policyType
placeholder="Filter policies"
mode="policy"
}}
{{#if filterFocused}}
{{#if filterMatchesKey}}
<p class="input-hint">
<kbd>ENTER</kbd> to go to <code>{{or pageFilter filter}}</code>
</p>
{{/if}}
{{#if firstPartialMatch}}
<p class="input-hint">
<kbd>TAB</kbd> to complete <code>{{firstPartialMatch.id}}</code>
</p>
{{/if}}
{{/if}}
{{#if firstPartialMatch}}
<p class="input-hint">
<kbd>TAB</kbd> to complete <code>{{firstPartialMatch.id}}</code>
</p>
{{/if}}
{{/if}}
</div>
</div>
</div>
</div>
{{#if model.meta.total}}
{{#each model as |item|}}
{{#if (eq item.id "root")}}
<div class="list-item-row is-flex" data-test-policy-item>
@ -139,30 +139,30 @@
</div>
{{/linked-block}}
{{/if}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link="vault.cluster.policies.index"
}}
{{/if}}
{{else}}
<div class="box is-sideless">
<p> There are no policies matching <code>{{pageFilter}}</code>. </p>
</div>
<EmptyState
@title="No policies matching &quot;{{pageFilter}}&quot;"
/>
{{/each}}
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey" data-test-no-policies-text>
There are currently no {{uppercase policyType}} policies.
</p>
</div>
</div>
</div>
</div>
{{/if}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link="vault.cluster.policies.index"
}}
<EmptyState
@title="No {{uppercase policyType}} policies yet"
@message="A list of policies will be listed here. Create your first {{uppercase policyType}} policy to get started."
>
{{#link-to "vault.cluster.policies.create" class="link"}}
Create {{uppercase policyType}} policy
{{/link-to}}
<LearnLink @path="/vault/getting-started/policies">
Learn More
</LearnLink>
</EmptyState>
{{/if}}
{{else}}
{{upgrade-page title="Sentinel" minimumEdition="Vault Enterprise Premium"}}

View File

@ -6,11 +6,9 @@
</h1>
</p.levelLeft>
</PageHeader>
<div class="box is-sideless has-background-white-bis has-text-grey has-text-centered">
<p>
The current cluster configuration does not support replication.
</p>
</div>
<EmptyState
@title="The current cluster configuration does not support replication"
/>
{{else}}
{{replication-summary
cluster=model

View File

@ -17,17 +17,9 @@
{{/info-table-row}}
</div>
{{else}}
<div class="box is-bottomless has-background-white-bis is-marginless">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
The secondary <code>{{model.config.id}}</code> does not currently have performance mount filtering configured.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="Performance Mount Filtering is not configured for this secondary"
/>
{{/if}}
<div class="field is-fullwidth box is-shadowless">
{{#if model.config.mode}}

View File

@ -46,17 +46,19 @@
<hr class="is-marginless" />
{{/each}}
{{else}}
<div class="box is-bottomless has-background-white-bis is-marginless">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">
There are currently no known {{performanceMode}} secondary clusters associated with this cluster.
</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="No known {{performanceMode}} secondary clusters associated with this cluster"
@message="Associated secondary clusters will be listed here. Add your first secondary cluster to get started."
>
{{#if model.canAddSecondary}}
{{#link-to 'vault.cluster.replication.mode.secondaries.add' model.name replicationMode class="link" }}
Add secondary
{{/link-to}}
{{/if}}
<DocLink @path="/docs/internals/replication.html">
Learn More
</DocLink>
</EmptyState>
{{/if}}
<div class="field is-grouped box is-shadowless is-fullwidth">
{{#if model.canAddSecondary}}

View File

@ -1,39 +1,39 @@
{{secret-list-header isCertTab=(eq tab "certs") model=backendModel baseKey=baseKey backendCrumb=backendCrumb filter=filter}}
{{#with (options-for-backend backendType tab) as |options|}}
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless">
<div class="level">
<div class="level-left">
{{navigate-input
enterpriseProduct="vault"
filterFocusDidChange=(action "setFilterFocus")
filterDidChange=(action "setFilter")
filter=filter
filterMatchesKey=filterMatchesKey
firstPartialMatch=firstPartialMatch
baseKey=(get baseKey "id")
shouldNavigateTree=options.navigateTree
placeholder=options.searchPlaceholder
mode=(if (eq tab 'certs') 'secrets-cert' 'secrets')
}}
{{#if filterFocused}}
{{#if filterMatchesKey}}
{{#unless filterIsFolder}}
{{#if model.meta.total}}
<div class="box is-sideless has-background-grey-lighter has-short-padding is-marginless">
<div class="level">
<div class="level-left">
{{navigate-input
enterpriseProduct="vault"
filterFocusDidChange=(action "setFilterFocus")
filterDidChange=(action "setFilter")
filter=filter
filterMatchesKey=filterMatchesKey
firstPartialMatch=firstPartialMatch
baseKey=(get baseKey "id")
shouldNavigateTree=options.navigateTree
placeholder=options.searchPlaceholder
mode=(if (eq tab 'certs') 'secrets-cert' 'secrets')
}}
{{#if filterFocused}}
{{#if filterMatchesKey}}
{{#unless filterIsFolder}}
<p class="input-hint">
<kbd>Enter</kbd> to view {{filter}}
</p>
{{/unless}}
{{/if}}
{{#if firstPartialMatch}}
<p class="input-hint">
<kbd>Enter</kbd> to view {{filter}}
<kbd>Tab</kbd> to autocomplete
</p>
{{/unless}}
{{/if}}
{{/if}}
{{#if firstPartialMatch}}
<p class="input-hint">
<kbd>Tab</kbd> to autocomplete
</p>
{{/if}}
{{/if}}
</div>
</div>
</div>
</div>
{{#if model.meta.total}}
{{#each model as |item|}}
{{partial options.listItemPartial}}
{{else}}
@ -45,27 +45,42 @@
{{/if}}
</div>
{{/each}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link=(concat "vault.cluster.secrets.backend.list" (if (not baseKey.id) "-root"))
model=(compact (array backend (if baseKey.id baseKey.id)))
}}
{{/if}}
{{else}}
<BlockEmpty>
{{#if (eq baseKey.id '')}}
There are currently no {{pluralize options.item}} in this backend.
{{else}}
{{#if filterIsFolder}}
{{#if (eq filter baseKey.id)}}
There are no {{pluralize options.item}} under <code>{{or filter}}</code>.
{{else}}
We couldn't find a folder matching <code>{{filter}}</code>.
{{/if}}
{{/if}}
{{#if (eq baseKey.id '')}}
<EmptyState
@title="No {{pluralize options.item}} in this backend yet"
@message="Secrets in this backend will be listed here. Add a secret to get started."
>
{{#secret-link
mode="create"
secret=''
queryParams=(query-params initialKey=(or filter baseKey.id))
class="link"
}}
{{options.create}}
{{/secret-link}}
</EmptyState>
{{else}}
{{#if filterIsFolder}}
<EmptyState
@title={{if (eq filter baseKey.id)
(concat
"No " (pluralize options.item) " under &quot;" this.filter "&quot;"
)
(concat
"No folders matching &quot;" this.filter "&quot;"
)
}}
/>
{{/if}}
</BlockEmpty>
{{/if}}
{{/if}}
{{/with}}
{{#if (gt model.meta.lastPage 1) }}
{{list-pagination
page=model.meta.currentPage
lastPage=model.meta.lastPage
link=(concat "vault.cluster.secrets.backend.list" (if (not baseKey.id) "-root"))
model=(compact (array backend (if baseKey.id baseKey.id)))
}}
{{/if}}

View File

@ -29,13 +29,7 @@
{{/confirm-action}}
</div>
{{else}}
<div class="box is-bottomless has-background-white-bis">
<div class="columns is-centered">
<div class="column is-half has-text-centered">
<div class="box is-shadowless has-background-white-bis">
<p class="has-text-grey">The token you are currently authenticated with does not have sufficient capabilities to seal this vault.</p>
</div>
</div>
</div>
</div>
<EmptyState
@title="This token does not have sufficient capabilities to seal this vault"
/>
{{/if}}

View File

@ -0,0 +1,43 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, find } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | empty-state', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`{{empty-state}}`);
assert.equal(this.element.textContent.trim(), '');
// Template block usage:
await render(hbs`
{{#empty-state
title="Empty State Title"
message="This is the empty state message"
}}
Actions Link
{{/empty-state}}
`);
assert.equal(
find('.empty-state-title').textContent.trim(),
'Empty State Title',
'renders empty state title'
);
assert.equal(
find('.empty-state-message').textContent.trim(),
'This is the empty state message',
'renders empty state message'
);
assert.equal(
find('.empty-state-actions').textContent.trim(),
'Actions Link',
'renders empty state actions'
);
});
});