Better empty state copy

This commit is contained in:
Joshua Ogle 2018-11-03 11:21:49 -06:00 committed by Matthew Irish
parent 70a12dcde6
commit 1a5e6fdce9
16 changed files with 105 additions and 57 deletions

View file

@ -1,5 +1,6 @@
import Component from '@ember/component';
export default Component.extend({
classNames: ['empty-state box is-sideless is-marginless is-fullwidth is-bottomless']
title: null,
classNames: ['empty-state box is-sideless is-marginless is-fullwidth is-bottomless'],
});

View file

@ -7,8 +7,12 @@ export default Component.extend({
items: null,
itemNoun: 'item',
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

@ -5,7 +5,7 @@ import { assign } from '@ember/polyfills';
const DEFAULT_DISPLAY = {
searchPlaceholder: 'Filter secrets',
item: 'secret',
create: 'Create secret',
create: 'Add secret',
navigateTree: true,
editComponent: 'secret-edit',
listItemPartial: 'partials/secret-list/item',
@ -15,7 +15,7 @@ const SECRET_BACKENDS = {
displayName: 'AWS',
searchPlaceholder: 'Filter roles',
item: 'role',
create: 'Create role',
create: 'Add role',
navigateTree: false,
editComponent: 'role-aws-edit',
listItemPartial: 'partials/secret-list/aws-role-item',
@ -30,7 +30,7 @@ const SECRET_BACKENDS = {
label: 'Roles',
searchPlaceholder: 'Filter roles',
item: 'role',
create: 'Create role',
create: 'Add role',
editComponent: 'role-pki-edit',
},
{
@ -39,7 +39,7 @@ const SECRET_BACKENDS = {
label: 'Certificates',
searchPlaceholder: 'Filter certificates',
item: 'certificates',
create: 'Create role',
create: 'Add role',
tab: 'certs',
listItemPartial: 'partials/secret-list/pki-cert-item',
editComponent: 'pki-cert-show',
@ -50,7 +50,7 @@ const SECRET_BACKENDS = {
displayName: 'SSH',
searchPlaceholder: 'Filter roles',
item: 'role',
create: 'Create role',
create: 'Add role',
navigateTree: false,
editComponent: 'role-ssh-edit',
listItemPartial: 'partials/secret-list/ssh-role-item',
@ -58,7 +58,7 @@ const SECRET_BACKENDS = {
transit: {
searchPlaceholder: 'Filter keys',
item: 'key',
create: 'Create encryption key',
create: 'Add encryption key',
navigateTree: false,
editComponent: 'transit-edit',
listItemPartial: 'partials/secret-list/item',

View file

@ -1,10 +1,10 @@
<div class="empty-state-content">
<h3 class="empty-state-title">
{{{title}}}
{{title}}
</h3>
{{#if message}}
<p class="empty-state-message">
{{{message}}}
{{message}}
</p>
{{/if}}
{{#if hasBlock}}

View file

@ -20,7 +20,7 @@
<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"}}
{{#link-to "vault.cluster.access.identity.aliases.edit" model.id tagName="button" class="link"}}
Edit {{lowercase (humanize model.identityType)}}
{{/link-to}}
<DocLink @href="https://learn.hashicorp.com/vault/identity-access-management/iam-identity">

View file

@ -29,6 +29,6 @@
{{/linked-block}}
{{else}}
<EmptyState
@title="There are no {{model.identityType}} aliases for {{model.name}}"
@title="No {{model.identityType}} aliases for {{model.name}} yet"
/>
{{/each}}

View file

@ -6,6 +6,7 @@
</div>
{{else}}
<EmptyState
@title={{emptyMessage}}
@title={{emptyTitle}}
@message={{emptyMessage}}
/>
{{/if}}

View file

@ -1,11 +1,20 @@
{{#if (and isV2 modelForData.destroyed)}}
<EmptyState
@title="Version {{modelForData.version}} of this secret has been permanently destroyed."
/>
@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 @href="https://www.vaultproject.io/docs/secrets/kv/kv-v2.html">
Learn More
</DocLink>
</EmptyState>
{{else if (and isV2 modelForData.deleted)}}
<EmptyState
@title="Version {{modelForData.version}} of this secret has been deleted."
/>
@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 @href="https://www.vaultproject.io/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

View file

@ -10,32 +10,30 @@
{{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" tagName="button" 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" tagName="button" 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

@ -7,7 +7,7 @@
</p.levelLeft>
<p.levelRight>
{{#link-to 'vault.cluster.access.namespaces.create' class="button has-icon-right is-ghost is-compact"}}
Create a namespace
Add namespace
<ICon @glyph="chevron-right" @size=11 />
{{/link-to}}
</p.levelRight>

View file

@ -18,7 +18,7 @@
</div>
{{else}}
<EmptyState
@title="The secondary <code>{{model.config.id}}</code> does not currently have performance mount filtering configured"
@title="Performance Mount Filtering is not configured for this secondary"
/>
{{/if}}
<div class="field is-fullwidth box is-shadowless">

View file

@ -48,7 +48,7 @@
{{else}}
<EmptyState
@title="No known {{performanceMode}} secondary clusters associated with this cluster"
@message="A list of secondary clusters will be listed here. Add your first secondary cluster to get started.">
@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 tagName="button" class="link" }}
Add secondary

View file

@ -55,16 +55,34 @@
{{/if}}
{{else}}
<div class="empty-state">
<div class="empty-state-title">
<div class="empty-state-content">
{{#if (eq baseKey.id '')}}
There are currently no {{pluralize options.item}} in this backend.
<div class="empty-state-title">
No {{pluralize options.item}} in this backend yet
</div>
<div class="empty-state-message">
Secrets in this backend will be listed here. Add a secret to get started.
</div>
<div class="empty-state-actions">
{{#secret-link
mode="create"
secret=''
queryParams=(query-params initialKey=(or filter baseKey.id))
class="link"
data-test-secret-create=true
}}
{{options.create}}
{{/secret-link}}
</div>
{{else}}
{{#if filterIsFolder}}
<div class="empty-state-title">
{{#if (eq filter baseKey.id)}}
There are no {{pluralize options.item}} under <code>{{or filter}}</code>.
No {{pluralize options.item}} under <code>{{or filter}}</code>
{{else}}
We couldn't find a folder matching <code>{{filter}}</code>.
No folders matching <code>{{filter}}</code>
{{/if}}
</div>
{{/if}}
{{/if}}
</div>

View file

@ -30,6 +30,6 @@
</div>
{{else}}
<EmptyState
@title="The token you are currently authenticated with does not have sufficient capabilities to seal this vault"
@title="This token does not have sufficient capabilities to seal this vault"
/>
{{/if}}

View file

@ -1,6 +1,6 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { render, find } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | empty-state', function(hooks) {
@ -16,11 +16,28 @@ module('Integration | Component | empty-state', function(hooks) {
// Template block usage:
await render(hbs`
{{#empty-state}}
template block text
{{#empty-state
title="Empty State Title"
message="This is the empty state message"
}}
Actions Link
{{/empty-state}}
`);
assert.equal(this.element.textContent.trim(), 'template block text');
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'
);
});
});