ui: Various empty state improvements/fixups (#11892)

* ui: Add login button to per service intentions for zero results

* Add login button and consistent header for when you have zero nodes

* `services` doesn't exists use `items` consequently:

Previous to this fix we would not show a more tailored message for when
you empty result set was due to a user search rather than an empty
result set straight from the backend

* Fix `error` > `@error` in ErrorState plus code formatting and more docs

* Changelog
This commit is contained in:
John Cowen 2021-12-21 06:49:18 +00:00 committed by GitHub
parent acc7f572fd
commit bb923d8705
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 23 deletions

3
.changelog/11892.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: Ensure a login buttons appear for some error states, plus text amends
```

View File

@ -7,8 +7,11 @@ for more details.
Using this component for all of our errors means we can show a consistent Using this component for all of our errors means we can show a consistent
error page for generic errors. error page for generic errors.
This component show slighltly different visuals and copy depending on the This component show slightly different visuals and copy depending on the
`status` of the error (the status is generally a HTTP error code) `status` of the error (the status is generally a HTTP error code).
Please note: The examples below use a `hash` for demonstration purposes, you'll
probably just be using an `error` object in real-life.
## Arguments ## Arguments
@ -17,12 +20,26 @@ This component show slighltly different visuals and copy depending on the
| `login` | `Function` | `undefined` | A login action to call when the login button is pressed (if not provided no login button will be shown | | `login` | `Function` | `undefined` | A login action to call when the login button is pressed (if not provided no login button will be shown |
| `error` | `Object` | `undefined` | 'Consul UI error shaped' JSON `{status: String, message: String, detail: String}` | | `error` | `Object` | `undefined` | 'Consul UI error shaped' JSON `{status: String, message: String, detail: String}` |
Specifically 403 errors **always** use the same header/body copy, this is hardcoded in and not currently overridable.
```hbs preview-template ```hbs preview-template
<ErrorState <ErrorState
@error={{hash status='403'}} @error={{hash status='403'}}
/> />
``` ```
Other StatusCodes have a global default text but these *are* overridable by using the message/detail properties of the Consul UI shaped errors.
```hbs preview-template
<ErrorState
@error={{hash
status='404'
message="`message` is what is shown in the header"
detail="`detail` is what shown in the body"
}}
/>
```
As with `EmptyState` you can optionally chose to show a login button using the As with `EmptyState` you can optionally chose to show a login button using the
`@login` argument. `@login` argument.

View File

@ -4,43 +4,63 @@
@login={{@login}} @login={{@login}}
> >
<BlockSlot @name="header"> <BlockSlot @name="header">
<h2>{{or @error.message "Consul returned an error"}}</h2> <h2>
{{or @error.message "Consul returned an error"}}
</h2>
</BlockSlot> </BlockSlot>
{{#if @error.status }} {{#if @error.status }}
<BlockSlot @name="subheader"> <BlockSlot @name="subheader">
<h3 data-test-status={{@error.status}}>Error {{@error.status}}</h3> <h3
data-test-status={{@error.status}}
>
Error {{@error.status}}
</h3>
</BlockSlot> </BlockSlot>
{{/if}} {{/if}}
<BlockSlot @name="body"> <BlockSlot @name="body">
{{#if error.detail}} <p>
<p> {{#if @error.detail}}
{{error.detail}} {{@error.detail}}
</p> {{else}}
{{else}}
<p>
You may have visited a URL that is loading an unknown resource, so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs. You may have visited a URL that is loading an unknown resource, so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.
</p> {{/if}}
{{/if}} </p>
</BlockSlot> </BlockSlot>
<BlockSlot @name="actions"> <BlockSlot @name="actions">
<li class="back-link"> <li class="back-link">
<a data-test-home rel="home" href={{href-to 'index'}}>Go back</a> <Action
data-test-home
@href={{href-to 'index'}}
>
Go back
</Action>
</li> </li>
<li class="docs-link"> <li class="docs-link">
<a href="{{env 'CONSUL_DOCS_URL'}}" rel="noopener noreferrer" target="_blank">Read the documentation</a> <Action
@href="{{env 'CONSUL_DOCS_URL'}}"
@external={{true}}
>
Read the documentation
</Action>
</li> </li>
</BlockSlot> </BlockSlot>
</EmptyState> </EmptyState>
{{else}} {{else}}
<EmptyState <EmptyState
class="status-403" class={{concat "status-" @error.status}}
@login={{@login}} @login={{@login}}
> >
<BlockSlot @name="header"> <BlockSlot @name="header">
<h2 data-test-status={{@error.status}}>You are not authorized</h2> <h2
data-test-status={{@error.status}}
>
You are not authorized
</h2>
</BlockSlot> </BlockSlot>
<BlockSlot @name="subheader"> <BlockSlot @name="subheader">
<h3>Error 403</h3> <h3>
Error {{@error.status}}
</h3>
</BlockSlot> </BlockSlot>
<BlockSlot @name="body"> <BlockSlot @name="body">
<p> <p>
@ -49,10 +69,20 @@
</BlockSlot> </BlockSlot>
<BlockSlot @name="actions"> <BlockSlot @name="actions">
<li class="docs-link"> <li class="docs-link">
<a href="{{env 'CONSUL_DOCS_URL'}}/acl/index.html" rel="noopener noreferrer" target="_blank">Read the documentation</a> <Action
@href="{{env 'CONSUL_DOCS_URL'}}/acl/index.html"
@external={{true}}
>
Read the documentation
</Action>
</li> </li>
<li class="learn-link"> <li class="learn-link">
<a href="{{env 'CONSUL_DOCS_LEARN_URL'}}/consul/security-networking/production-acls" rel="noopener noreferrer" target="_blank">Follow the guide</a> <Action
@href="{{env 'CONSUL_DOCS_LEARN_URL'}}/consul/security-networking/production-acls"
@external={{true}}
>
Follow the guide
</Action>
</li> </li>
</BlockSlot> </BlockSlot>
</EmptyState> </EmptyState>

View File

@ -90,7 +90,18 @@ as |route|>
/> />
</collection.Collection> </collection.Collection>
<collection.Empty> <collection.Empty>
<EmptyState> <EmptyState
@login={{route.model.app.login.open}}
>
<BlockSlot @name="header">
<h2>
{{#if (gt items.length 0)}}
No nodes found
{{else}}
Welcome to Nodes
{{/if}}
</h2>
</BlockSlot>
<BlockSlot @name="body"> <BlockSlot @name="body">
<p> <p>
There don't seem to be any registered nodes, or you may not have access to view nodes yet. There don't seem to be any registered nodes, or you may not have access to view nodes yet.

View File

@ -105,7 +105,7 @@ as |sort filters items partition nspace|}}
> >
<BlockSlot @name="header"> <BlockSlot @name="header">
<h2> <h2>
{{#if (gt services.length 0)}} {{#if (gt items.length 0)}}
No services found No services found
{{else}} {{else}}
Welcome to Services Welcome to Services
@ -114,7 +114,7 @@ as |sort filters items partition nspace|}}
</BlockSlot> </BlockSlot>
<BlockSlot @name="body"> <BlockSlot @name="body">
<p> <p>
{{#if (gt services.length 0)}} {{#if (gt items.length 0)}}
No services where found matching that search, or you may not have access to view the services you are searching for. No services where found matching that search, or you may not have access to view the services you are searching for.
{{else}} {{else}}
There don't seem to be any registered services, or you may not have access to view services yet. There don't seem to be any registered services, or you may not have access to view services yet.

View File

@ -89,7 +89,9 @@ as |route|>
</Consul::Intention::List> </Consul::Intention::List>
</collection.Collection> </collection.Collection>
<collection.Empty> <collection.Empty>
<EmptyState> <EmptyState
@login={{route.model.app.login.open}}
>
<BlockSlot @name="header"> <BlockSlot @name="header">
<h2> <h2>
{{#if (gt items.length 0)}} {{#if (gt items.length 0)}}