ui: Move control of login modal to use JS rather than HTML (label/id) (#9883)
* Add before and after skip links portals * Move EmptyState and ErrorState to use a @login action/function * Move page title setting to the Route component * Add Routes and Outlets everywhere, and use those to access login modal * Add some aria-labels to the modals * Docs * Remove the label/input now we no longer need it, fixup pageobject * Add basic modal docs * Switch out old toggle names for ids * Wrap nspace Route template in a Route component * type > class
This commit is contained in:
parent
af78561018
commit
489b60105f
|
@ -5,6 +5,9 @@
|
|||
</h1>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<ErrorState @error={{@error}} @allowLogin={{eq @error.status "403"}} />
|
||||
<ErrorState
|
||||
@error={{@error}}
|
||||
@login={{if (eq @error.status "403") @login}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
|
|
|
@ -108,7 +108,7 @@
|
|||
@error={{hash
|
||||
status='403'
|
||||
}}
|
||||
@allowLogin={{true}}
|
||||
@login={{login}}
|
||||
/>
|
||||
{{else}}
|
||||
<YieldSlot @name="content">{{yield}}</YieldSlot>
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
class="app"
|
||||
...attributes
|
||||
>
|
||||
<ModalLayer />
|
||||
|
||||
<div
|
||||
class="skip-links"
|
||||
{{on "click" this.focus}}
|
||||
>
|
||||
<PortalTarget
|
||||
@name="app-before-skip-links"
|
||||
@mutiple={{true}}
|
||||
></PortalTarget>
|
||||
<a href={{concat '#' exported.main}}>{{t 'components.app.skip_to_content'}}</a>
|
||||
{{!--
|
||||
In order to add further skip links from within other templates use:
|
||||
|
@ -21,11 +24,13 @@
|
|||
from within your template
|
||||
--}}
|
||||
<PortalTarget
|
||||
@name="app-skip-links"
|
||||
@name="app-after-skip-links"
|
||||
@mutiple={{true}}
|
||||
></PortalTarget>
|
||||
</div>
|
||||
|
||||
<ModalLayer />
|
||||
|
||||
<input
|
||||
type="checkbox"
|
||||
id={{concat guid "-main-nav-toggle"}}
|
||||
|
|
|
@ -193,6 +193,9 @@
|
|||
<ModalDialog
|
||||
class="consul-intention-permission-modal"
|
||||
@onclose={{action (mut permission) undefined}}
|
||||
@aria={{hash
|
||||
label="Edit Permission"
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
|
|
|
@ -38,6 +38,9 @@ as |api|>
|
|||
<ModalDialog
|
||||
class="consul-intention-action-warn-modal warning"
|
||||
data-test-action-warning
|
||||
@aria={{hash
|
||||
label=(concat "Set intention to " newAction)
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
class: ember
|
||||
---
|
||||
# EmptyState
|
||||
|
||||
Consul UIs default 'empty state' used for when we retrive an empty result set,
|
||||
whether that set is successful or erroneous. This is mainly used via the
|
||||
`ErrorState` component, so also consider using that directly instead of this
|
||||
component if dealing with errors.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `login` | `Function` | `undefined` | A login action to call when the login button is pressed (if not provided no login button will be shown |
|
||||
|
||||
Icons are controlled via a `status-xxx` class. `xxx` should be some sort of
|
||||
3 digit error code, special icons are used for `404` and `403`, otherwise a
|
||||
generic icon will be used. To add any further special icons please add to the
|
||||
component's `skin` file.
|
||||
|
||||
If the `@login` attribute is provided, a button will be shown directly
|
||||
underneath the body text clicking on which will fire the provided `@login`
|
||||
function.
|
||||
|
||||
```hbs preview-template
|
||||
<EmptyState
|
||||
class="status-404"
|
||||
@login={{noop}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
Header
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="subheader">
|
||||
<h3>
|
||||
Subheader
|
||||
</h3>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Body text
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<li class="docs-link">
|
||||
<a
|
||||
href="{{env 'CONSUL_DOCS_URL'}}/agent/kv"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Documentation on K/V
|
||||
</a>
|
||||
</li>
|
||||
<li class="learn-link">
|
||||
<a
|
||||
href="{{env 'CONSUL_DOCS_LEARN_URL'}}/consul/getting-started/kv"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Read the guide
|
||||
</a>
|
||||
</li>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
```
|
||||
|
||||
The component has four slots for specifying header, subheader, body and
|
||||
'actions', although the component will show a minimal empty slot if only the
|
||||
body slot is specified:
|
||||
|
||||
```hbs preview-template
|
||||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Minimal text
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
```
|
|
@ -16,8 +16,11 @@
|
|||
{{#yield-slot name="body"}}
|
||||
<div>
|
||||
{{yield}}
|
||||
{{#if (and (env 'CONSUL_ACLS_ENABLED') allowLogin)}}
|
||||
<label for="login-toggle" data-test-empty-state-login>
|
||||
{{#if login}}
|
||||
<Action
|
||||
data-test-empty-state-login
|
||||
{{on "click" login}}
|
||||
>
|
||||
<DataSource
|
||||
@src="settings://consul:token"
|
||||
@onchange={{action (mut token) value="data"}}
|
||||
|
@ -27,7 +30,7 @@
|
|||
{{else}}
|
||||
Log in
|
||||
{{/if}}
|
||||
</label>
|
||||
</Action>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/yield-slot}}
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
%empty-state > ul > li > label > button {
|
||||
@extend %empty-state-anchor;
|
||||
}
|
||||
%empty-state label {
|
||||
%empty-state div > button {
|
||||
@extend %primary-button;
|
||||
}
|
|
@ -15,8 +15,9 @@
|
|||
width: 370px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
%empty-state label {
|
||||
margin: 0 auto !important;
|
||||
%empty-state button {
|
||||
margin: 0 auto;
|
||||
display: inline;
|
||||
}
|
||||
%empty-state-header {
|
||||
margin-bottom: -3px;
|
|
@ -0,0 +1,34 @@
|
|||
# ErrorState
|
||||
|
||||
Consul UIs default 'error state' used when an error is returned form the
|
||||
backend. This component used `EmptyState` internally, so please refer to that
|
||||
for more details.
|
||||
|
||||
Using this component for all of our errors means we can show a consistent
|
||||
error page for generic errors.
|
||||
|
||||
This component show slighltly different visuals and copy depending on the
|
||||
`status` of the error (the status is generally a HTTP error code)
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `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}` |
|
||||
|
||||
```hbs preview-template
|
||||
<ErrorState
|
||||
@error={{hash status='403'}}
|
||||
/>
|
||||
```
|
||||
|
||||
As with `EmptyState` you can optionally chose to show a login button using the
|
||||
`@login` argument.
|
||||
|
||||
```hbs preview-template
|
||||
<ErrorState
|
||||
@error={{hash status='403'}}
|
||||
@login={{noop}}
|
||||
/>
|
||||
```
|
|
@ -1,38 +0,0 @@
|
|||
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
<Meta title="Components/ErrorState" />
|
||||
|
||||
# ErrorState
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Basic"
|
||||
argTypes={{
|
||||
allowLogin: {
|
||||
defaultValue: true,
|
||||
control: {
|
||||
type: 'boolean'
|
||||
}
|
||||
},
|
||||
status: {
|
||||
defaultValue: '403',
|
||||
control: {
|
||||
type: 'select',
|
||||
options: [
|
||||
'404',
|
||||
'403',
|
||||
'500'
|
||||
]
|
||||
}
|
||||
}
|
||||
}}
|
||||
>{(args) => ({
|
||||
template: hbs`<ErrorState
|
||||
@allowLogin={{allowLogin}}
|
||||
@error={{hash status=status}}
|
||||
/>`,
|
||||
context: args
|
||||
})}
|
||||
</Story>
|
||||
</Canvas>
|
|
@ -1,7 +1,7 @@
|
|||
{{#if (not-eq @error.status "403")}}
|
||||
<EmptyState
|
||||
class={{concat "status-" @error.status}}
|
||||
@allowLogin={{@allowLogin}}
|
||||
@login={{@login}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>{{or @error.message "Consul returned an error"}}</h2>
|
||||
|
@ -34,7 +34,7 @@
|
|||
{{else}}
|
||||
<EmptyState
|
||||
class="status-403"
|
||||
@allowLogin={{@allowLogin}}
|
||||
@login={{@login}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2 data-test-status={{@error.status}}>You are not authorized</h2>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -218,14 +218,28 @@
|
|||
>
|
||||
{{#let components.AuthForm components.AuthProfile as |AuthForm AuthProfile|}}
|
||||
<BlockSlot @name="unauthorized">
|
||||
<label
|
||||
tabindex="0"
|
||||
{{on 'keypress' this.keypressClick}}
|
||||
<Portal @target="app-before-skip-links">
|
||||
<button
|
||||
type="button"
|
||||
{{on "click" (optional this.modal.open)}}
|
||||
>
|
||||
<span>Log in</span>
|
||||
</label>
|
||||
<ModalDialog @name="login-toggle" @onclose={{this.close}} @onopen={{this.open}} as |modal|>
|
||||
Login
|
||||
</button>
|
||||
</Portal>
|
||||
<button
|
||||
type="button"
|
||||
{{on "click" (optional this.modal.open)}}
|
||||
>
|
||||
Log in
|
||||
</button>
|
||||
<ModalDialog
|
||||
@name="login-toggle"
|
||||
@onclose={{this.close}}
|
||||
@onopen={{this.open}}
|
||||
@aria={{hash
|
||||
label="Log in to Consul"
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
<h2>Log in to Consul</h2>
|
||||
|
@ -245,7 +259,14 @@
|
|||
</ModalDialog>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="authorized">
|
||||
<ModalDialog @name="login-toggle" @onclose={{this.close}} @onopen={{this.open}} as |modal|>
|
||||
<ModalDialog
|
||||
@name="login-toggle"
|
||||
@onclose={{this.close}}
|
||||
@onopen={{this.open}}
|
||||
@aria={{hash
|
||||
label="Log in with a different token"
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
<h2>Log in with a different token</h2>
|
||||
|
@ -261,6 +282,14 @@
|
|||
</button>
|
||||
</BlockSlot>
|
||||
</ModalDialog>
|
||||
<Portal @target="app-before-skip-links">
|
||||
<button
|
||||
type="button"
|
||||
{{on "click" (optional authDialog.logout)}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</Portal>
|
||||
<PopoverMenu @position="right" as |components api|>
|
||||
<BlockSlot @name="trigger">
|
||||
Logout
|
||||
|
@ -295,7 +324,7 @@
|
|||
|
||||
<:main>
|
||||
{{yield (hash
|
||||
modal=this.modal
|
||||
login=(if (env 'CONSUL_ACLS_ENABLED') this.modal (hash open=undefined))
|
||||
)}}
|
||||
</:main>
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ export default (collection, clickable, attribute, is, authForm, emptyState) => s
|
|||
status: attribute('data-test-status', '[data-test-status]'),
|
||||
},
|
||||
};
|
||||
page.navigation.login = clickable('[data-test-main-nav-auth] label');
|
||||
page.navigation.login = clickable('[data-test-main-nav-auth] button');
|
||||
page.navigation.dc = clickable('[data-test-datacenter-menu] button');
|
||||
page.navigation.nspace = clickable('[data-test-nspace-menu] button');
|
||||
page.navigation.manageNspaces = clickable('[data-test-main-nav-nspaces] a');
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
/* things that should look like nav buttons */
|
||||
%main-nav-horizontal > ul > li > a,
|
||||
%main-nav-horizontal > ul > li > span,
|
||||
%main-nav-horizontal > ul > li > label,
|
||||
%main-nav-horizontal > ul > li > button,
|
||||
%main-nav-horizontal > ul > li > .popover-menu > label > button {
|
||||
@extend %main-nav-horizontal-action;
|
||||
}
|
||||
%main-nav-horizontal .popover-menu [type='checkbox']:checked + label > *,
|
||||
%main-nav-horizontal > ul > li.is-active > a,
|
||||
%main-nav-horizontal > ul > li.is-active > label > * {
|
||||
%main-nav-horizontal > ul > li.is-active > button {
|
||||
@extend %main-nav-horizontal-action-active;
|
||||
}
|
||||
/* Whilst we want spans to look the same as actions */
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
class: ember
|
||||
---
|
||||
# ModalDialog
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `onopen` | `Function` | `undefined` | A function to call when the modal has opened |
|
||||
| `onclose` | `Function` | `undefined` | A function to call when the modal has closed |
|
||||
| `aria` | `Object` | `undefined` | A `hash` of aria properties used in the component, currently only label is supported |
|
||||
|
||||
## Exports
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `open` | `Function` | Opens the modal dialog |
|
||||
| `close` | `Function` | Closes the modal dialog |
|
||||
|
||||
Works in tandem with `<ModalLayer />` to render modals. First of all ensure
|
||||
you have a modal layer on the page (it doesn't have to be in the same
|
||||
template)
|
||||
|
||||
```hbs
|
||||
<ModalLayer />
|
||||
```
|
||||
|
||||
Then all modals will be rendered into the `<ModalLayer />` for example:
|
||||
|
||||
```hbs preview-template
|
||||
<ModalDialog
|
||||
@onclose={{noop}}
|
||||
@onopen={{noop}}
|
||||
@aria={{hash
|
||||
label="Screenread name of the modal"
|
||||
}}
|
||||
as |modal|>
|
||||
|
||||
<!-- Save a reference to the modal component so we can call its methods -->
|
||||
{{did-insert (set this 'modal' modal)}}
|
||||
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
Modal Header
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Modal body
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<button type="button"
|
||||
{{on "click" modal.close}}
|
||||
>
|
||||
Close modal
|
||||
</button>
|
||||
</BlockSlot>
|
||||
</ModalDialog>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
{{on 'click' (optional this.modal.open)}}
|
||||
>
|
||||
Open Modal
|
||||
</button>
|
||||
|
||||
```
|
|
@ -1,10 +1,8 @@
|
|||
{{#let (hash
|
||||
labelledby=(unique-id)
|
||||
) as |aria|}}
|
||||
<Portal @target="modal">
|
||||
{{yield}}
|
||||
<input
|
||||
id={{@name}}
|
||||
type="checkbox"
|
||||
{{on 'change' (action 'change')}}
|
||||
/>
|
||||
<div
|
||||
class="modal-dialog"
|
||||
aria-hidden="true"
|
||||
|
@ -16,6 +14,7 @@
|
|||
<div
|
||||
class="modal-dialog-modal"
|
||||
role="dialog"
|
||||
aria-label={{@aria.label}}
|
||||
>
|
||||
<div
|
||||
role="document"
|
||||
|
@ -31,6 +30,7 @@
|
|||
{{yield (hash
|
||||
open=(action "open")
|
||||
close=(action "close")
|
||||
aria=aria
|
||||
)}}
|
||||
</YieldSlot>
|
||||
</header>
|
||||
|
@ -39,6 +39,7 @@
|
|||
{{yield (hash
|
||||
open=(action "open")
|
||||
close=(action "close")
|
||||
aria=aria
|
||||
)}}
|
||||
</YieldSlot>
|
||||
</div>
|
||||
|
@ -47,6 +48,7 @@
|
|||
{{yield (hash
|
||||
open=(action "open")
|
||||
close=(action "close")
|
||||
aria=aria
|
||||
)}}
|
||||
</YieldSlot>
|
||||
</footer>
|
||||
|
@ -54,3 +56,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</Portal>
|
||||
{{/let}}
|
|
@ -21,8 +21,5 @@ export default Component.extend(Slotted, {
|
|||
close: function() {
|
||||
this.dialog.hide();
|
||||
},
|
||||
change: function(e) {
|
||||
this.actions.open.call(this);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# ModalLayer
|
||||
|
||||
A component to give you control over where `<ModalDialog />` components are
|
||||
rendered. Please see `<ModalDialog />` for more details.
|
||||
|
||||
```hbs
|
||||
<ModalLayer />
|
||||
```
|
|
@ -0,0 +1,43 @@
|
|||
# Outlet
|
||||
|
||||
The `Outlet` component should be used to wrap *every* ember `{{outlet}}`. It
|
||||
provides/will provide functionality (along with the `<Route />` component)
|
||||
for setting and announcing the title of the page, passing data down through
|
||||
the route/template hierarchy, automatic orchestration of nested routing and
|
||||
visual animating/transitioning between routes.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `name` | `String` | `undefined` | The name of the route in ember routeName format e.g. `dc.services.index`. This is generally the `routeName` variable that is available to you in all Consul UI route/page level templates.|
|
||||
| `model` | `Object` | `undefined` | Arbitrary hash of data to pass down to the child route (available in the `<Route as |route|>` export). |
|
||||
|
||||
|
||||
```hbs
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{hash
|
||||
dc=(hash
|
||||
Name="dc-1"
|
||||
)
|
||||
}}
|
||||
>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
```
|
||||
|
||||
Currently, using the `<Outlet />` component means that every single page/route
|
||||
template is wrapped in a HTML `<section>` element. This `<section>` element
|
||||
has various data attributes attached to indiciate the loading state of the
|
||||
outlet. These can be used to specifically target every individual outlet via
|
||||
CSS.
|
||||
|
||||
## Attributes
|
||||
|
||||
| Data Attribute | Description |
|
||||
| --- | --- |
|
||||
| `data-outlet` | The name of this outlet in ember routeName format e.g. `dc.services.index` |
|
||||
| `data-route` | The name of the current child route of this outlet in ember routeName format e.g. `dc.services.show` |
|
||||
| `data-state` | The current state of this outlet, `idle` or `loading` |
|
||||
| `data-transition` | A combination of `idle` and `loading` states |
|
|
@ -1,5 +1,6 @@
|
|||
{{yield}}
|
||||
<fieldset
|
||||
class="policy-form"
|
||||
disabled={{if (not (can "write policy" item=item)) "disabled"}}
|
||||
...attributes
|
||||
>
|
||||
|
|
|
@ -27,8 +27,11 @@
|
|||
{{!the modal has to go here so that if you provide a slot to trigger it doesn't get rendered}}
|
||||
<ModalDialog
|
||||
data-test-policy-form
|
||||
id="new-policy"
|
||||
@onopen={{action "open"}}
|
||||
@name="new-policy-toggle"
|
||||
@aria={{hash
|
||||
label='New Policy'
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
|
|
|
@ -5,7 +5,7 @@ export default (clickable, deletable, collection, alias, policyForm) => (
|
|||
return {
|
||||
scope: scope,
|
||||
create: clickable(createSelector),
|
||||
form: policyForm('#new-policy-toggle + div'),
|
||||
form: policyForm('#new-policy'),
|
||||
policies: alias('selectedOptions'),
|
||||
selectedOptions: collection(
|
||||
'[data-test-policies] [data-test-tabular-row]',
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
{{yield}}
|
||||
<fieldset
|
||||
disabled={{if (not (can "write role" item=item)) "disabled"}}
|
||||
class="role-form"
|
||||
disabled={{if (not (can "write role" item=item)) "disabled"}}
|
||||
data-test-role-form
|
||||
...attributes
|
||||
>
|
||||
<label class="type-text{{if item.error.Name ' has-error'}}">
|
||||
<span>Name</span>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
<ModalDialog
|
||||
class="role-selector"
|
||||
data-test-role-form
|
||||
id="new-role"
|
||||
@onclose={{action (mut state) "role"}}
|
||||
@name="new-role-toggle"
|
||||
@aria={{hash
|
||||
label=(if (eq state 'role') 'New Role' 'New Policy')
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# Route
|
||||
|
||||
The `Route` component should be used for the top-level component for *every*
|
||||
route/page template. It provides/will provide functionality (along with the
|
||||
`<Outlet />` component) for setting and announcing the title of the page,
|
||||
passing data down through the route/template hierarchy, automatic
|
||||
orchestration of nested routing and visual animating/transitioning between
|
||||
routes.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `name` | `String` | `undefined` | The name of the route in ember routeName format e.g. `dc.services.index`. This is generally the `routeName` variable that is available to you in all Consul UI route/page level templates.|
|
||||
| `title` | `String` | `undefined` | The title for this page (eventually passed through to the `{{page-title}}` helper. This argument should be omitted if a title change isn't required. |
|
||||
| `titleSeparator` | `String` | `undefined` | This can be used in the top-level route to configure the separator for the `{{page-title}}` helper |
|
||||
|
||||
## Exports
|
||||
|
||||
| export | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `model` | `Object` | `undefined` | Arbitrary hash of data passed down from the parent route/outlet |
|
||||
|
||||
```hbs
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Page Title"
|
||||
@titleSeparator=" - "
|
||||
as |route|>
|
||||
{{route.model.dc.Name}}
|
||||
</Route>
|
||||
```
|
||||
|
||||
Every page/route template has a `routeName` variable exposed specifically to
|
||||
allow you to use this to set the `@name` of the route.
|
|
@ -1,5 +1,10 @@
|
|||
{{did-insert this.connect}}
|
||||
{{will-destroy this.disconnect}}
|
||||
|
||||
{{#if this.title}}
|
||||
{{page-title this.title separator=@titleSeparator}}
|
||||
{{/if}}
|
||||
|
||||
{{yield (hash
|
||||
model=model
|
||||
)}}
|
|
@ -8,10 +8,15 @@ export default class RouteComponent extends Component {
|
|||
|
||||
@tracked model;
|
||||
|
||||
get title() {
|
||||
return this.args.title;
|
||||
}
|
||||
|
||||
@action
|
||||
connect() {
|
||||
this.routlet.addRoute(this.args.name, this);
|
||||
}
|
||||
|
||||
@action
|
||||
disconnect() {
|
||||
this.routlet.removeRoute(this.args.name, this);
|
||||
|
|
|
@ -2,11 +2,20 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
left: 50%;
|
||||
padding: 20px;
|
||||
top: -100px;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
%skip-links div,
|
||||
%skip-links button,
|
||||
%skip-links a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
%skip-links:focus-within {
|
||||
top: 0px;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
color: $white;
|
||||
background-color: $blue-500;
|
||||
}
|
||||
%skip-links button,
|
||||
%skip-links a {
|
||||
color: inherit;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
|
||||
<ModalDialog
|
||||
class="sparkline-key"
|
||||
@aria={{hash
|
||||
label="Metrics Key"
|
||||
}}
|
||||
as |modal|>
|
||||
<Ref @target={{this}} @name="modal" @value={{modal}} />
|
||||
<BlockSlot @name="header">
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
%visually-hidden {
|
||||
position: absolute !important;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
clip: rect(0 0 0 0);
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
%visually-hidden-text {
|
||||
text-indent: -9000px;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@import './empty-state/index';
|
||||
@import 'consul-ui/components/empty-state/index';
|
||||
.empty-state {
|
||||
@extend %empty-state;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
@title='Consul'
|
||||
@titleSeparator=" - "
|
||||
>
|
||||
{{page-title 'Consul' separator=' - '}}
|
||||
|
||||
{{#if (env 'CONSUL_ACLS_ENABLED')}}
|
||||
{{document-attrs class="has-acls"}}
|
||||
|
@ -28,9 +29,12 @@ as |source|>
|
|||
@nspaces={{nspaces}}
|
||||
@nspace={{or nspace nspaces.firstObject}}
|
||||
@onchange={{action "reauthorize"}}
|
||||
>
|
||||
as |consul|>
|
||||
<Outlet
|
||||
@name="application"
|
||||
@model={{hash
|
||||
app=consul
|
||||
}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
|
|
|
@ -1 +1,10 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{route.model}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
</Route>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
{{#if isAuthorized }}
|
||||
{{page-title 'Auth Methods'}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Auth Methods"
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -38,10 +36,12 @@ as |sort filters items|}}
|
|||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Access Controls
|
||||
{{route.model.hi}}
|
||||
Auth Methods
|
||||
</h1>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
|
@ -66,7 +66,9 @@ as |sort filters items|}}
|
|||
<Consul::AuthMethod::List @items={{collection.items}} />
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -99,4 +101,4 @@ as |sort filters items|}}
|
|||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if create 'New ACL' 'Edit ACL'}}
|
||||
as |route|>
|
||||
<AppView>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Acl::Notifications
|
||||
|
@ -46,3 +50,4 @@
|
|||
{{ partial 'dc/acls/form'}}
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
|
@ -1,4 +1,7 @@
|
|||
{{page-title 'ACLs'}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="ACLs"
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -67,7 +70,9 @@ as |sort filters items|}}
|
|||
</Consul::Acl::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -93,3 +98,4 @@ as |sort filters items|}}
|
|||
</AppView>
|
||||
|
||||
{{/let}}
|
||||
</Route>
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
<ModalDialog
|
||||
data-test-delete-modal
|
||||
@onclose={{action cancel}}
|
||||
@aria={{hash
|
||||
label="Policy in Use"
|
||||
}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>Policy in Use</h2>
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
{{#if isAuthorized }}
|
||||
{{#if create }}
|
||||
{{page-title 'New Policy'}}
|
||||
{{else}}
|
||||
{{page-title 'Edit Policy'}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if isAuthorized (if create 'New Policy' 'Edit Policy') 'Access Controls'}}
|
||||
as |route|>
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Policy::Notifications
|
||||
|
@ -59,3 +55,4 @@
|
|||
{{/if}}
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
|
@ -1,8 +1,7 @@
|
|||
{{#if isAuthorized }}
|
||||
{{page-title 'Policies'}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Policies"
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -35,6 +34,7 @@ as |sort filters items|}}
|
|||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Policy::Notifications
|
||||
|
@ -79,7 +79,9 @@ as |sort filters items|}}
|
|||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -113,3 +115,4 @@ as |sort filters items|}}
|
|||
</AppView>
|
||||
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -24,7 +24,12 @@
|
|||
</BlockSlot>
|
||||
<BlockSlot @name="dialog" as |execute cancel message|>
|
||||
{{#if (gt items.length 0)}}
|
||||
<ModalDialog @onclose={{action cancel}}>
|
||||
<ModalDialog
|
||||
@onclose={{action cancel}}
|
||||
@aria={{hash
|
||||
label="Role in Use"
|
||||
}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>Role in Use</h2>
|
||||
</BlockSlot>
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
{{#if isAuthorized }}
|
||||
{{#if item.ID}}
|
||||
{{page-title 'Edit Role'}}
|
||||
{{else}}
|
||||
{{page-title 'New Role'}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if isAuthorized (if create 'New Role' 'Edit Role') 'Access Controls'}}
|
||||
as |route|>
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Role::Notifications
|
||||
|
@ -51,3 +47,4 @@
|
|||
{{ partial 'dc/acls/roles/form'}}
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
|
@ -1,9 +1,7 @@
|
|||
{{#if isAuthorized }}
|
||||
{{page-title 'Roles'}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Roles"
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -29,6 +27,7 @@ as |sort filters items|}}
|
|||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Role::Notifications
|
||||
|
@ -73,7 +72,9 @@ as |sort filters items|}}
|
|||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -106,3 +107,4 @@ as |sort filters items|}}
|
|||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -1,15 +1,11 @@
|
|||
{{#if isAuthorized }}
|
||||
{{#if create}}
|
||||
{{page-title 'New Token'}}
|
||||
{{else}}
|
||||
{{page-title 'Edit Token'}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if isAuthorized (if create 'New Token' 'Edit Token') 'Access Controls'}}
|
||||
as |route|>
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Token::Notifications
|
||||
|
@ -96,3 +92,4 @@
|
|||
{{ partial 'dc/acls/tokens/form'}}
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
|
@ -1,9 +1,7 @@
|
|||
{{#if isAuthorized }}
|
||||
{{page-title 'Tokens'}}
|
||||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Tokens"
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -33,6 +31,7 @@ as |sort filters items|}}
|
|||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Token::Notifications
|
||||
|
@ -95,7 +94,9 @@ as |sort filters items|}}
|
|||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -120,3 +121,4 @@ as |sort filters items|}}
|
|||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
</Route>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
{{#if item.ID}}
|
||||
{{page-title 'Edit Intention'}}
|
||||
{{else}}
|
||||
{{page-title 'New Intention'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if item.ID 'Edit Intention' 'New Intention'}}
|
||||
as |route|>
|
||||
<AppView>
|
||||
<BlockSlot @name="breadcrumbs">
|
||||
<ol>
|
||||
|
@ -31,3 +30,4 @@
|
|||
/>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
|
@ -1,8 +1,14 @@
|
|||
{{page-title 'Intentions'}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Intentions"
|
||||
as |route|>
|
||||
<DataLoader @src={{concat '/' nspace '/' dc '/intentions'}} as |api|>
|
||||
|
||||
<BlockSlot @name="error">
|
||||
<AppError @error={{api.error}} />
|
||||
<AppError
|
||||
@error={{api.error}}
|
||||
@login={{route.model.app.login.open}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="loaded">
|
||||
|
@ -82,7 +88,9 @@ as |sort filters items|}}
|
|||
</Consul::Intention::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -120,3 +128,4 @@ as |sort filters items|}}
|
|||
{{/let}}
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
||||
</Route>
|
|
@ -1,8 +1,7 @@
|
|||
{{#if item.Key }}
|
||||
{{page-title 'Edit Key/Value'}}
|
||||
{{else}}
|
||||
{{page-title 'New Key/Value'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if item.Key 'Edit Key/Value' 'New Key/Value'}}
|
||||
as |route|>
|
||||
<AppView>
|
||||
<BlockSlot @name="breadcrumbs">
|
||||
<ol>
|
||||
|
@ -55,3 +54,4 @@
|
|||
{{/if}}
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
|
@ -1,4 +1,7 @@
|
|||
{{page-title 'Key/Value'}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Key/Value"
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -81,7 +84,9 @@ as |sort filters items|}}
|
|||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -116,3 +121,4 @@ as |sort filters items|}}
|
|||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -1,4 +1,7 @@
|
|||
{{page-title 'Nodes'}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title="Nodes"
|
||||
as |route|>
|
||||
<EventSource @src={{items}} />
|
||||
<EventSource @src={{leader}} />
|
||||
{{#let
|
||||
|
@ -72,3 +75,4 @@ as |sort filters items|}}
|
|||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -1,4 +1,7 @@
|
|||
{{page-title item.Node}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{item.Node}}
|
||||
as |route|>
|
||||
<DataLoader as |loader|>
|
||||
|
||||
<BlockSlot @name="data">
|
||||
|
@ -7,7 +10,10 @@
|
|||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="error">
|
||||
<AppError @error={{loader.error}} />
|
||||
<AppError
|
||||
@error={{loader.error}}
|
||||
@login={{route.model.app.login.open}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="disconnected" as |Notification|>
|
||||
|
@ -72,6 +78,7 @@
|
|||
<BlockSlot @name="content">
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{route.model}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
|
@ -80,3 +87,4 @@
|
|||
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -68,3 +71,4 @@ as |sort filters items|}}
|
|||
</DataCollection>
|
||||
</div>
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
{{#if item.Meta}}
|
||||
<Consul::Metadata::List @items={{entries item.Meta}} />
|
||||
|
@ -11,3 +14,4 @@
|
|||
</EmptyState>
|
||||
{{/if}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
<div class="definition-table">
|
||||
<dl>
|
||||
|
@ -23,4 +26,4 @@
|
|||
</div>
|
||||
<Consul::Tomography::Graph @distances={{tomography.distances}} />
|
||||
</div>
|
||||
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -69,3 +72,4 @@ as |sort filters items|}}
|
|||
</DataCollection>
|
||||
</div>
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<EventSource @src={{sessions}} />
|
||||
<div class="tab-section">
|
||||
{{#if (gt sessions.length 0)}}
|
||||
|
@ -6,7 +9,9 @@
|
|||
@onInvalidate={{action send 'invalidateSession'}}
|
||||
/>
|
||||
{{else}}
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
Welcome to Lock Sessions
|
||||
|
@ -28,3 +33,4 @@
|
|||
</EmptyState>
|
||||
{{/if}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
{{#if create }}
|
||||
{{page-title 'New Namespace'}}
|
||||
{{else}}
|
||||
{{page-title 'Edit Namespace'}}
|
||||
{{/if}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{if create 'New Namespace' 'Edit Namespace'}}
|
||||
as |route|>
|
||||
<AppView>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Nspace::Notifications
|
||||
|
@ -31,3 +30,4 @@
|
|||
{{ partial 'dc/nspaces/form'}}
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
</Route>
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
{{page-title 'Namespaces'}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title='Namespaces'
|
||||
as |route|>
|
||||
<EventSource @src={{items}} />
|
||||
{{#let
|
||||
|
||||
|
@ -65,7 +68,9 @@ as |sort filters items|}}
|
|||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
|
@ -98,3 +103,4 @@ as |sort filters items|}}
|
|||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
</Route>
|
|
@ -1,7 +1,7 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
>
|
||||
{{page-title 'Services'}}
|
||||
@title="Services"
|
||||
as |route|>
|
||||
|
||||
<EventSource @src={{items}} />
|
||||
|
||||
|
@ -76,7 +76,9 @@ as |sort filters items|}}
|
|||
</Consul::Service::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<EmptyState
|
||||
@login={{route.model.app.login.open}}
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt services.length 0)}}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
{{page-title item.Service.ID}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{item.Service.ID}}
|
||||
as |route|>
|
||||
<DataLoader as |loader|>
|
||||
|
||||
<BlockSlot @name="data">
|
||||
|
@ -10,7 +13,10 @@
|
|||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="error">
|
||||
<AppError @error={{loader.error}} />
|
||||
<AppError
|
||||
@error={{loader.error}}
|
||||
@login={{route.model.app.login.open}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="disconnected" as |Notification|>
|
||||
|
@ -88,6 +94,7 @@
|
|||
}}/>
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{route.model}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
|
@ -95,3 +102,4 @@
|
|||
</AppView>
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
||||
</Route>
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
{{#if item.Service.TaggedAddresses }}
|
||||
<TabularCollection
|
||||
|
@ -26,3 +29,4 @@
|
|||
</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
{{#if (gt proxy.Service.Proxy.Expose.Paths.length 0)}}
|
||||
<p>
|
||||
|
@ -14,3 +17,4 @@
|
|||
</EmptyState>
|
||||
{{/if}}
|
||||
</div>
|
||||
</Route>
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
|
@ -66,3 +69,4 @@ as |sort filters items|}}
|
|||
|
||||
</div>
|
||||
{{/let}}
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
<section class="tags">
|
||||
<h2>Tags</h2>
|
||||
|
@ -28,3 +31,4 @@
|
|||
{{/if}}
|
||||
</section>
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
{{#let
|
||||
|
||||
|
@ -58,3 +61,4 @@ as |sort filters items|}}
|
|||
</DataCollection>
|
||||
{{/let}}
|
||||
</div>
|
||||
</Route>
|
|
@ -1,8 +1,8 @@
|
|||
{{#let items.firstObject as |item|}}
|
||||
<Route
|
||||
@name={{routeName}}
|
||||
@title={{item.Service.Service}}
|
||||
as |route|>
|
||||
{{#let items.firstObject as |item|}}
|
||||
{{page-title item.Service.Service}}
|
||||
<DataLoader as |loader|>
|
||||
|
||||
<BlockSlot @name="data">
|
||||
|
@ -14,7 +14,10 @@ as |route|>
|
|||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="error">
|
||||
<AppError @error={{loader.error}} />
|
||||
<AppError
|
||||
@error={{loader.error}}
|
||||
@login={{route.model.app.login.open}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="disconnected" as |Notification|>
|
||||
|
@ -107,6 +110,7 @@ as |route|>
|
|||
<BlockSlot @name="content">
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{route.model}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
|
@ -114,5 +118,5 @@ as |route|>
|
|||
</AppView>
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
||||
{{/let}}
|
||||
</Route>
|
||||
{{/let}}
|
|
@ -1,6 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
>
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
{{#let
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{route.model}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<Consul::Intention::Form
|
||||
@nspace={{nspace}}
|
||||
@dc={{dc}}
|
||||
|
@ -7,3 +10,4 @@
|
|||
}}
|
||||
@onsubmit={{transition-to 'dc.services.show.intentions.index'}}
|
||||
/>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<DataLoader
|
||||
@src={{uri
|
||||
'/${nspace}/${dc}/intentions/for-service/${slug}'
|
||||
|
@ -94,3 +97,4 @@ as |sort filters items|}}
|
|||
{{/let}}
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
||||
</Route>
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<EventSource @src={{chain}} />
|
||||
<div class="tab-section">
|
||||
<Consul::DiscoveryChain
|
||||
@chain={{chain.Chain}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<EventSource @src={{items}} />
|
||||
<div class="tab-section">
|
||||
{{#let
|
||||
|
@ -66,3 +69,4 @@ as |sort filters items|}}
|
|||
</DataCollection>
|
||||
{{/let}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<div class="tab-section">
|
||||
{{#let (flatten (map-by "Tags" items)) as |tags|}}
|
||||
{{#if (gt tags.length 0) }}
|
||||
|
@ -13,3 +16,4 @@
|
|||
{{/if}}
|
||||
{{/let}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<EventSource @src={{topology}} />
|
||||
<div class="tab-section">
|
||||
{{#if (and (eq topology.Upstreams.length 0) (eq topology.Downstreams.length 0))}}
|
||||
|
@ -37,3 +40,4 @@
|
|||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<EventSource @src={{items}} />
|
||||
<div class="tab-section">
|
||||
{{#let
|
||||
|
@ -66,3 +69,4 @@ as |sort filters items|}}
|
|||
</DataCollection>
|
||||
{{/let}}
|
||||
</div>
|
||||
</Route>
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<Route
|
||||
@name={{routeName}}
|
||||
as |route|>
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{route.model}}
|
||||
as |o|>
|
||||
{{outlet}}
|
||||
</Outlet>
|
||||
</Route>
|
||||
|
|
|
@ -51,7 +51,7 @@ Feature: dc / acls / roles / as-many / add-new: Add new
|
|||
And "[data-notification]" has the "notification-update" class
|
||||
And "[data-notification]" has the "success" class
|
||||
Scenario: Add Role that has an existing Policy
|
||||
And I click "#new-role-toggle + div .ember-power-select-trigger"
|
||||
And I click "#new-role .ember-power-select-trigger"
|
||||
And I click ".ember-power-select-option:first-child"
|
||||
And I click submit on the roles.form
|
||||
Then a PUT request was made to "/v1/acl/role?dc=datacenter" from yaml
|
||||
|
|
Loading…
Reference in New Issue