ui: Redesigns for the token/policy/roles listings pages (#8144)
This commit is contained in:
parent
c5d0216939
commit
ed8d148502
|
@ -0,0 +1,3 @@
|
|||
<li class="dangerous">
|
||||
<button tabindex="-1" type="button" onclick={{action onclick}}>{{yield}}</button>
|
||||
</li>
|
|
@ -0,0 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
{{yield}}
|
||||
<div class="confirmation-alert" ...attributes>
|
||||
<div>
|
||||
<header>
|
||||
<YieldSlot @name="header">{{yield}}</YieldSlot>
|
||||
</header>
|
||||
<YieldSlot @name="body">{{yield}}</YieldSlot>
|
||||
</div>
|
||||
<ul>
|
||||
<YieldSlot @name="confirm" @params={{
|
||||
block-params (component 'confirmation-alert/action'
|
||||
onclick=(action onclick)
|
||||
)
|
||||
}}
|
||||
>
|
||||
{{yield}}
|
||||
</YieldSlot>
|
||||
<li>
|
||||
<label for={{name}}>Cancel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
## ConsulPolicyList
|
||||
|
||||
```
|
||||
<ConsulPolicyList
|
||||
@items={{items}}
|
||||
@ondelete={{action 'delete'}}
|
||||
/>
|
||||
```
|
||||
|
||||
A presentational component for rendering Consul ACL policies
|
||||
|
||||
### Arguments
|
||||
|
||||
| Argument/Attribute | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `items` | `array` | | An array of ACL policies |
|
||||
| `ondelete` | `function` | | An action to execute when the `Delete` action is clicked |
|
||||
|
||||
### See
|
||||
|
||||
- [Component Source Code](./index.js)
|
||||
- [TemplateSource Code](./index.hbs)
|
||||
|
||||
---
|
|
@ -0,0 +1,67 @@
|
|||
{{#if (gt items.length 0)}}
|
||||
<ListCollection @items={{items}} class="consul-policy-list" as |item|>
|
||||
<BlockSlot @name="header">
|
||||
{{#if (eq (policy/typeof item) 'policy-management')}}
|
||||
<dl class="policy-management">
|
||||
<dd>
|
||||
<Tooltip @position="top-start">
|
||||
Global Management Policy
|
||||
</Tooltip>
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
<a data-test-policy={{item.Name}} href={{href-to 'dc.acls.policies.edit' item.ID}} class={{if (eq (policy/typeof item) 'policy-management') 'is-management'}}>{{item.Name}}</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="details">
|
||||
<dl class="datacenter">
|
||||
<dt>
|
||||
<Tooltip @position="top-start">Datacenters</Tooltip>
|
||||
</dt>
|
||||
<dd>
|
||||
{{join ', ' (policy/datacenters item)}}
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="description">
|
||||
<dt>Description</dt>
|
||||
<dd data-test-description>
|
||||
{{item.Description}}
|
||||
</dd>
|
||||
</dl>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions" as |Actions|>
|
||||
<Actions as |Action|>
|
||||
<Action data-test-edit-action @href={{href-to 'dc.acls.policies.edit' item.ID}}>
|
||||
<BlockSlot @name="label">
|
||||
{{#if (eq (policy/typeof item) 'policy-management')}}
|
||||
View
|
||||
{{else}}
|
||||
Edit
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{#if (not-eq (policy/typeof item) 'policy-management')}}
|
||||
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
||||
<BlockSlot @name="label">
|
||||
Delete
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||
<Confirmation class="warning">
|
||||
<BlockSlot @name="header">
|
||||
Confirm delete
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Are you sure you want to delete this policy?
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirm" as |Confirm|>
|
||||
<Confirm>Delete</Confirm>
|
||||
</BlockSlot>
|
||||
</Confirmation>
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{/if}}
|
||||
</Actions>
|
||||
</BlockSlot>
|
||||
</ListCollection>
|
||||
{{/if}}
|
|
@ -0,0 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
export default (collection, clickable, attribute, text, actions) => () => {
|
||||
return collection('.consul-policy-list li:not(:first-child)', {
|
||||
name: attribute('data-test-policy', '[data-test-policy]'),
|
||||
description: text('[data-test-description]'),
|
||||
policy: clickable('a'),
|
||||
...actions(['edit', 'delete']),
|
||||
});
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
## ConsulRoleList
|
||||
|
||||
```
|
||||
<ConsulRoleList
|
||||
@items={{items}}
|
||||
@ondelete={{action 'delete'}}
|
||||
/>
|
||||
```
|
||||
|
||||
A presentational component for rendering Consul ACL roles
|
||||
|
||||
### Arguments
|
||||
|
||||
| Argument/Attribute | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `items` | `array` | | An array of ACL roles |
|
||||
| `ondelete` | `function` | | An action to execute when the `Delete` action is clicked |
|
||||
|
||||
### See
|
||||
|
||||
- [Component Source Code](./index.js)
|
||||
- [TemplateSource Code](./index.hbs)
|
||||
|
||||
---
|
|
@ -0,0 +1,45 @@
|
|||
{{#if (gt items.length 0)}}
|
||||
<ListCollection @items={{items}} class="consul-role-list" as |item|>
|
||||
<BlockSlot @name="header">
|
||||
<a data-test-role={{item.Name}} href={{href-to 'dc.acls.roles.edit' item.ID}}>{{item.Name}}</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="details">
|
||||
<ConsulTokenRulesetList @item={{item}} />
|
||||
<dl>
|
||||
<dt>Description</dt>
|
||||
<dd data-test-description>
|
||||
{{item.Description}}
|
||||
</dd>
|
||||
</dl>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions" as |Actions|>
|
||||
<Actions as |Action|>
|
||||
<Action data-test-edit-action @href={{href-to 'dc.acls.roles.edit' item.ID}}>
|
||||
<BlockSlot @name="label">
|
||||
Edit
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
||||
<BlockSlot @name="label">
|
||||
Delete
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||
<Confirmation class="warning">
|
||||
<BlockSlot @name="header">
|
||||
Confirm delete
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Are you sure you want to delete this role?
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirm" as |Confirm|>
|
||||
<Confirm>Delete</Confirm>
|
||||
</BlockSlot>
|
||||
</Confirmation>
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
</Actions>
|
||||
</BlockSlot>
|
||||
</ListCollection>
|
||||
{{/if}}
|
|
@ -0,0 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
export default (collection, clickable, attribute, text, actions) => () => {
|
||||
return collection('.consul-role-list li:not(:first-child)', {
|
||||
name: attribute('data-test-role', '[data-test-role]'),
|
||||
description: text('[data-test-description]'),
|
||||
policy: text('[data-test-policy].policy', { multiple: true }),
|
||||
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
|
||||
...actions(['edit', 'delete']),
|
||||
});
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
{{#if (gt items.length 0)}}
|
||||
<ListCollection @items={{items}} class="consul-token-list" as |item index checked change|>
|
||||
<ListCollection @items={{items}} class="consul-token-list" as |item|>
|
||||
<BlockSlot @name="header">
|
||||
{{#if (eq item.AccessorID token.AccessorID)}}
|
||||
<dl rel="me">
|
||||
<dd>
|
||||
<Tooltip>
|
||||
<Tooltip @position="top-start">
|
||||
Your token
|
||||
</Tooltip>
|
||||
</dd>
|
||||
|
@ -19,50 +19,7 @@
|
|||
{{if item.Local 'local' 'global' }}
|
||||
</dd>
|
||||
</dl>
|
||||
{{#let (policy/group item.Policies) as |policies|}}
|
||||
{{#let (get policies 'management') as |management|}}
|
||||
{{#if (gt management.length 0)}}
|
||||
<dl>
|
||||
<dt>
|
||||
Management
|
||||
</dt>
|
||||
<dd>
|
||||
{{#each (get policies 'management') as |item|}}
|
||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{#let (get policies 'identities') as |identities|}}
|
||||
{{#if (gt identities.length 0)}}
|
||||
<dl>
|
||||
<dt>Identities</dt>
|
||||
<dd>
|
||||
{{#each identities as |item|}}
|
||||
<span data-test-policy class={{policy/typeof item}}>{{if (eq item.template 'service-identity') 'Service' 'Node'}} Identity: {{item.Name}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{#let (append (get policies 'policies') item.Roles) as |policies|}}
|
||||
{{#if (gt policies.length 0)}}
|
||||
<dl>
|
||||
<dt>Rules</dt>
|
||||
<dd>
|
||||
{{#if (token/is-legacy item) }}
|
||||
Legacy tokens have embedded rules.
|
||||
{{ else }}
|
||||
{{#each policies as |item|}}
|
||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
<ConsulTokenRulesetList @item={{item}} />
|
||||
<dl>
|
||||
<dt>Description</dt>
|
||||
<dd data-test-description>
|
||||
|
@ -70,98 +27,86 @@
|
|||
</dd>
|
||||
</dl>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<div class="more-popover-menu">
|
||||
<PopoverMenu @expanded={{if (eq checked index) true false}} @onchange={{action change index}} @keyboardAccess={{false}} @submenus={{array "logout" "use" "delete"}}>
|
||||
<BlockSlot @name="trigger">
|
||||
More
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||
<li role="none">
|
||||
<a data-test-edit role="menuitem" tabindex="-1" href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>Edit</a>
|
||||
</li>
|
||||
{{#if (not (token/is-legacy item))}}
|
||||
<li role="none">
|
||||
<button role="menuitem" tabindex="-1" type="button" data-test-clone {{action onclone item}}>Duplicate</button>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (eq item.AccessorID token.AccessorID) }}
|
||||
<li role="none" class="dangerous">
|
||||
<label for={{concat confirm 'logout'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-logout>Log out</label>
|
||||
<div role="menu">
|
||||
<div class="confirmation-alert warning">
|
||||
<div>
|
||||
<header>
|
||||
Confirm logout
|
||||
</header>
|
||||
<p>
|
||||
Are you sure you want to stop using this ACL token? This will log you out.
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="dangerous">
|
||||
<button tabindex="-1" type="button" onclick={{action onlogout item}}>Logout</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for={{concat confirm 'logout'}}>Cancel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{else}}
|
||||
<li role="none">
|
||||
<label for={{concat confirm 'use'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-use>Use</label>
|
||||
<div role="menu">
|
||||
<div class="confirmation-alert warning">
|
||||
<div>
|
||||
<header>
|
||||
Confirm use
|
||||
</header>
|
||||
<p>
|
||||
Are you sure you want to use this ACL token?
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="dangerous">
|
||||
<button data-test-confirm-use tabindex="-1" type="button" onclick={{action onuse item}}>Use</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for={{concat confirm 'use'}}>Cancel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#unless (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)) }}
|
||||
<li role="none" class="dangerous">
|
||||
<label for={{concat confirm 'delete'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
||||
<div role="menu">
|
||||
<div class="confirmation-alert warning">
|
||||
<div>
|
||||
<header>
|
||||
Confirm Delete
|
||||
</header>
|
||||
<p>
|
||||
Are you sure you want to delete this token?
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="dangerous">
|
||||
<button tabindex="-1" type="button" class="type-delete" onclick={{action ondelete item}}>Delete</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for={{concat confirm 'delete'}}>Cancel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/unless}}
|
||||
</BlockSlot>
|
||||
</PopoverMenu>
|
||||
</div>
|
||||
<BlockSlot @name="actions" as |Actions|>
|
||||
<Actions as |Action|>
|
||||
<Action data-test-edit-action @href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>
|
||||
<BlockSlot @name="label">
|
||||
Edit
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{#if (not (token/is-legacy item))}}
|
||||
<Action data-test-clone-action @onclick={{action onclone item}}>
|
||||
<BlockSlot @name="label">
|
||||
Duplicate
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{/if}}
|
||||
{{#if (eq item.AccessorID token.AccessorID)}}
|
||||
<Action data-test-logout-action class="dangerous" @onclick={{action onclone item}}>
|
||||
<BlockSlot @name="label">
|
||||
Logout
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||
<Confirmation class="warning">
|
||||
<BlockSlot @name="header">
|
||||
Confirm logout
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Are you sure you want to stop using this ACL token? This will log you out.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirm" as |Confirm|>
|
||||
<Confirm>Logout</Confirm>
|
||||
</BlockSlot>
|
||||
</Confirmation>
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{else}}
|
||||
<Action data-test-use-action @onclick={{action onuse item}}>
|
||||
<BlockSlot @name="label">
|
||||
Use
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||
<Confirmation class="warning">
|
||||
<BlockSlot @name="header">
|
||||
Confirm use
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Are you sure you want to use this ACL token?
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirm" as |Confirm|>
|
||||
<Confirm>Use</Confirm>
|
||||
</BlockSlot>
|
||||
</Confirmation>
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{/if}}
|
||||
{{#if (not (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)))}}
|
||||
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
||||
<BlockSlot @name="label">
|
||||
Delete
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||
<Confirmation class="warning">
|
||||
<BlockSlot @name="header">
|
||||
Confirm delete
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
Are you sure you want to delete this token?
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="confirm" as |Confirm|>
|
||||
<Confirm>Delete</Confirm>
|
||||
</BlockSlot>
|
||||
</Confirmation>
|
||||
</BlockSlot>
|
||||
</Action>
|
||||
{{/if}}
|
||||
</Actions>
|
||||
</BlockSlot>
|
||||
</ListCollection>
|
||||
{{/if}}
|
|
@ -1,4 +1,4 @@
|
|||
export default (collection, clickable, attribute, text, deletable) => () => {
|
||||
export default (collection, clickable, attribute, text, actions) => () => {
|
||||
return collection('.consul-token-list li:not(:first-child)', {
|
||||
id: attribute('data-test-token', '[data-test-token]'),
|
||||
description: text('[data-test-description]'),
|
||||
|
@ -6,10 +6,6 @@ export default (collection, clickable, attribute, text, deletable) => () => {
|
|||
role: text('[data-test-policy].role', { multiple: true }),
|
||||
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
|
||||
token: clickable('a'),
|
||||
actions: clickable('label'),
|
||||
use: clickable('[data-test-use]'),
|
||||
confirmUse: clickable('[data-test-confirm-use]'),
|
||||
clone: clickable('[data-test-clone]'),
|
||||
...deletable(),
|
||||
...actions(['edit', 'delete', 'use', 'logout', 'clone']),
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
## ConsulTokenRulesetList
|
||||
|
||||
```
|
||||
<ConsulTokenRulesetList
|
||||
@item={{item}}
|
||||
/>
|
||||
```
|
||||
|
||||
A presentational component for rendering Consul ACL token 'rulesets'. Rulesets are the various 'rule-type' things that belong to a token such as policies, identities and roles, and in the case of legacy tokens, the old style string based rules property.
|
||||
|
||||
### Arguments
|
||||
|
||||
| Argument/Attribute | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `item` | `array` | | An ACL token |
|
||||
|
||||
### See
|
||||
|
||||
- [Component Source Code](./index.js)
|
||||
- [TemplateSource Code](./index.hbs)
|
||||
|
||||
---
|
|
@ -0,0 +1,49 @@
|
|||
{{#let (policy/group item.Policies) as |policies|}}
|
||||
{{#let (get policies 'management') as |management|}}
|
||||
{{#if (gt management.length 0)}}
|
||||
<dl>
|
||||
<dt>
|
||||
Management
|
||||
</dt>
|
||||
<dd>
|
||||
{{#each (get policies 'management') as |item|}}
|
||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{#let (get policies 'identities') as |identities|}}
|
||||
{{#if (gt identities.length 0)}}
|
||||
<dl>
|
||||
<dt>Identities</dt>
|
||||
<dd>
|
||||
{{#each identities as |item|}}
|
||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{#if (token/is-legacy item) }}
|
||||
<dl>
|
||||
<dt>Rules</dt>
|
||||
<dd>
|
||||
Legacy tokens have embedded rules.
|
||||
</dd>
|
||||
</dl>
|
||||
{{else}}
|
||||
{{#let (append (get policies 'policies') (or item.Roles (array))) as |policies|}}
|
||||
{{#if (gt policies.length 0)}}
|
||||
<dl>
|
||||
<dt>Rules</dt>
|
||||
<dd>
|
||||
{{#each policies as |item|}}
|
||||
<span data-test-policy class={{policy/typeof item}}>{{item.Name}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
</dl>
|
||||
{{/if}}
|
||||
{{/let}}
|
||||
{{/if}}
|
||||
{{/let}}
|
|
@ -0,0 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -11,9 +11,17 @@
|
|||
<li></li>
|
||||
{{~#each _cells as |cell|~}}
|
||||
<li onclick={{action 'click'}} style={{{cell.style}}} class={{if (service/exists cell.item) 'linkable'}}>
|
||||
<YieldSlot @name="header"><div>{{yield cell.item cell.index checked (action "change")}}</div></YieldSlot>
|
||||
<YieldSlot @name="details"><div>{{yield cell.item cell.index checked (action "change")}}</div></YieldSlot>
|
||||
<YieldSlot @name="actions"><div>{{yield cell.item cell.index checked (action "change")}}</div></YieldSlot>
|
||||
<YieldSlot @name="header"><div>{{yield cell.item cell.index}}</div></YieldSlot>
|
||||
<YieldSlot @name="details"><div>{{yield cell.item cell.index}}</div></YieldSlot>
|
||||
<YieldSlot @name="actions"
|
||||
@params={{
|
||||
block-params (component 'more-popover-menu' expanded=(if (eq checked cell.index) true false) onchange=(action "change" cell.index))
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
{{yield cell.item cell.index}}
|
||||
</div>
|
||||
</YieldSlot>
|
||||
</li>
|
||||
{{~/each~}}
|
||||
</EmberNativeScrollable>
|
|
@ -1,15 +1,21 @@
|
|||
{{yield}}
|
||||
{{#let (hash
|
||||
change=(action "change")
|
||||
) as |api|}}
|
||||
<div class="menu-panel {{position}}">
|
||||
<YieldSlot @name="controls">
|
||||
{{yield}}
|
||||
{{yield api}}
|
||||
</YieldSlot>
|
||||
{{#yield-slot name="header"}}
|
||||
<div>{{yield}}</div>
|
||||
<div>
|
||||
{{yield api}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{/yield-slot}}
|
||||
<ul role="menu" ...attributes>
|
||||
<YieldSlot @name="menu">
|
||||
{{yield}}
|
||||
{{yield api}}
|
||||
</YieldSlot>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/let}}
|
|
@ -1,7 +1,26 @@
|
|||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
import Slotted from 'block-slots';
|
||||
|
||||
export default Component.extend(Slotted, {
|
||||
tagName: '',
|
||||
dom: service('dom'),
|
||||
actions: {
|
||||
change: function(e) {
|
||||
const id = e.target.getAttribute('id');
|
||||
const $trigger = this.dom.element(`[for='${id}']`);
|
||||
const $panel = this.dom.element('[role=menu]', $trigger.parentElement);
|
||||
const $menuPanel = this.dom.closest('.menu-panel', $panel);
|
||||
if (e.target.checked) {
|
||||
$panel.style.display = 'block';
|
||||
const height = $panel.offsetHeight + 2;
|
||||
$menuPanel.style.maxHeight = $menuPanel.style.minHeight = `${height}px`;
|
||||
} else {
|
||||
$panel.style.display = null;
|
||||
$menuPanel.style.maxHeight = null;
|
||||
$menuPanel.style.minHeight = '0';
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{{yield}}
|
||||
<li role="none" ...attributes>
|
||||
{{#if hasConfirmation}}
|
||||
<label for={{concat menu.confirm guid}} role="menuitem" tabindex="-1" onkeypress={{menu.keypressClick}}>
|
||||
<YieldSlot @name="label">{{yield}}</YieldSlot>
|
||||
</label>
|
||||
<div role="menu">
|
||||
<YieldSlot @name="confirmation" @params={{
|
||||
block-params (component 'confirmation-alert'
|
||||
onclick=(action onclick)
|
||||
name=(concat menu.confirm guid)
|
||||
)
|
||||
}}>{{yield}}</YieldSlot>
|
||||
</div>
|
||||
{{else if href}}
|
||||
<a role="menuitem" tabindex="-1" href={{href}}>
|
||||
<YieldSlot @name="label">
|
||||
{{yield}}
|
||||
</YieldSlot>
|
||||
</a>
|
||||
{{else}}
|
||||
<button role="menuitem" tabindex="-1" type="button" onclick={{action this.onclick}}>
|
||||
<YieldSlot @name="label">
|
||||
{{yield}}
|
||||
</YieldSlot>
|
||||
</button>
|
||||
{{/if}}
|
||||
</li>
|
|
@ -0,0 +1,26 @@
|
|||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { set } from '@ember/object';
|
||||
|
||||
import Slotted from 'block-slots';
|
||||
|
||||
export default Component.extend(Slotted, {
|
||||
tagName: '',
|
||||
dom: service('dom'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.guid = this.dom.guid(this);
|
||||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
this.menu.addSubmenu(this.guid);
|
||||
},
|
||||
didDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
this.menu.removeSubmenu(this.guid);
|
||||
},
|
||||
willRender: function() {
|
||||
this._super(...arguments);
|
||||
set(this, 'hasConfirmation', this._isRegistered('confirmation'));
|
||||
},
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
<div class="more-popover-menu">
|
||||
<PopoverMenu @expanded={{expanded}} @onchange={{action onchange}} @keyboardAccess={{false}} as |api|>
|
||||
<BlockSlot @name="trigger">
|
||||
More
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||
{{yield (component 'more-popover-menu/action' menu=(hash
|
||||
addSubmenu=api.addSubmenu
|
||||
removeSubmenu=api.removeSubmenu
|
||||
confirm=confirm
|
||||
keypressClick=keypressClick
|
||||
))}}
|
||||
</BlockSlot>
|
||||
</PopoverMenu>
|
||||
</div>
|
|
@ -0,0 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
export default (clickable, confirmation) => (actions, scope) => {
|
||||
return actions.reduce(
|
||||
(prev, item) => {
|
||||
const itemScope = `[data-test-${item}-action]`;
|
||||
return {
|
||||
...prev,
|
||||
[item]: clickable(`${itemScope} [role='menuitem']`),
|
||||
[`confirm${item.charAt(0).toUpperCase()}${item.substr(1)}`]: clickable(
|
||||
`${itemScope} [role='menu'] button`
|
||||
),
|
||||
};
|
||||
},
|
||||
{
|
||||
actions: clickable('label'),
|
||||
}
|
||||
);
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
{{yield (concat 'popover-menu-' guid)}}
|
||||
{{yield}}
|
||||
<AriaMenu @keyboardAccess={{keyboardAccess}} as |change keypress ariaLabelledBy ariaControls ariaExpanded keypressClick|>
|
||||
<ToggleButton
|
||||
@checked={{if keyboardAccess ariaExpanded expanded}}
|
||||
|
@ -7,25 +7,35 @@
|
|||
<Ref @target={{this}} @name="toggle" @value={{api}} />
|
||||
<button type="button" aria-haspopup="menu" onkeydown={{keypress}} onclick={{this.toggle.click}} id={{ariaLabelledBy}} aria-controls={{ariaControls}}>
|
||||
<YieldSlot @name="trigger">
|
||||
{{yield}}
|
||||
{{yield (hash
|
||||
addSubmenu=(action 'addSubmenu')
|
||||
removeSubmenu=(action 'removeSubmenu')
|
||||
)}}
|
||||
</YieldSlot>
|
||||
</button>
|
||||
</ToggleButton>
|
||||
<MenuPanel @position={{position}} id={{ariaControls}} aria-labelledby={{ariaLabelledBy}} aria-expanded={{ariaExpanded}}>
|
||||
<MenuPanel @position={{position}} id={{ariaControls}} aria-labelledby={{ariaLabelledBy}} aria-expanded={{ariaExpanded}} as |api|>
|
||||
<BlockSlot @name="controls">
|
||||
<input type="checkbox" id={{concat 'popover-menu-' guid '-'}} />
|
||||
{{#each submenus as |sub|}}
|
||||
<input type="checkbox" id={{concat 'popover-menu-' guid '-' sub}} />
|
||||
{{/each}}
|
||||
{{#each submenus as |sub|}}
|
||||
<input type="checkbox" id={{concat 'popover-menu-' guid '-' sub}} onchange={{api.change}} />
|
||||
{{/each}}
|
||||
</BlockSlot>
|
||||
{{#if hasHeader}}
|
||||
<BlockSlot @name="header">
|
||||
{{#yield-slot name="header"}}{{yield}}{{else}}{{/yield-slot}}
|
||||
{{yield (hash
|
||||
addSubmenu=(action 'addSubmenu')
|
||||
removeSubmenu=(action 'removeSubmenu')
|
||||
)}}
|
||||
{{#yield-slot name="header"}}{{else}}{{/yield-slot}}
|
||||
</BlockSlot>
|
||||
{{/if}}
|
||||
<BlockSlot @name="menu">
|
||||
<YieldSlot @name="menu" @params={{block-params (concat "popover-menu-" guid "-") send keypressClick this.toggle.click}}>
|
||||
{{yield}}
|
||||
{{yield (hash
|
||||
addSubmenu=(action 'addSubmenu')
|
||||
removeSubmenu=(action 'removeSubmenu')
|
||||
)}}
|
||||
</YieldSlot>
|
||||
</BlockSlot>
|
||||
</MenuPanel>
|
||||
|
|
|
@ -16,11 +16,22 @@ export default Component.extend(Slotted, {
|
|||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.guid = this.dom.guid(this);
|
||||
this.submenus = [];
|
||||
},
|
||||
willRender: function() {
|
||||
set(this, 'hasHeader', this._isRegistered('header'));
|
||||
},
|
||||
actions: {
|
||||
addSubmenu: function(name) {
|
||||
set(this, 'submenus', this.submenus.concat(name));
|
||||
},
|
||||
removeSubmenu: function(name) {
|
||||
const pos = this.submenus.indexOf(name);
|
||||
if (pos !== -1) {
|
||||
this.submenus.splice(pos, 1);
|
||||
set(this, 'submenus', this.submenus);
|
||||
}
|
||||
},
|
||||
change: function(e) {
|
||||
if (!e.target.checked) {
|
||||
[...this.dom.elements(`[id^=popover-menu-${this.guid}]`)].forEach(function($item) {
|
||||
|
|
|
@ -3,13 +3,16 @@ import { get } from '@ember/object';
|
|||
const MANAGEMENT_ID = '00000000-0000-0000-0000-000000000001';
|
||||
export function typeOf(params, hash) {
|
||||
const item = params[0];
|
||||
const template = get(item, 'template');
|
||||
switch (true) {
|
||||
case typeof template === 'undefined':
|
||||
return 'role';
|
||||
case template === 'service-identity':
|
||||
return 'policy-service-identity';
|
||||
case template === 'node-identity':
|
||||
return 'policy-node-identity';
|
||||
case get(item, 'ID') === MANAGEMENT_ID:
|
||||
return 'policy-management';
|
||||
case typeof get(item, 'template') === 'undefined':
|
||||
return 'role';
|
||||
case get(item, 'template') !== '':
|
||||
return 'policy-service-identity';
|
||||
default:
|
||||
return 'policy';
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
background-color: $yellow-050;
|
||||
border-top-left-radius: $decor-radius-200;
|
||||
border-top-right-radius: $decor-radius-200;
|
||||
cursor: default;
|
||||
}
|
||||
%confirmation-alert > ul {
|
||||
list-style: none;
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
%menu-panel [type='checkbox'] {
|
||||
display: none;
|
||||
}
|
||||
%menu-panel [type='checkbox'] ~ * {
|
||||
transition: transform 150ms, min-height 150ms, max-height 150ms;
|
||||
%menu-panel {
|
||||
overflow: hidden;
|
||||
transition: min-height 150ms, max-height 150ms;
|
||||
min-height: 0;
|
||||
}
|
||||
%menu-panel [type='checkbox'] ~ * {
|
||||
transition: transform 150ms;
|
||||
}
|
||||
%menu-panel [type='checkbox']:checked ~ * {
|
||||
transform: translateX(calc(-100% - 10px));
|
||||
/* this needs to autocalculate */
|
||||
/* or be hardcoded */
|
||||
/* min-height: 143px; */
|
||||
}
|
||||
%menu-panel [role='menuitem'] {
|
||||
display: flex;
|
||||
|
@ -27,7 +28,19 @@
|
|||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(100% + 10px);
|
||||
display: none;
|
||||
}
|
||||
/* TODO: once everything is using ListCollection */
|
||||
/* this can go */
|
||||
%menu-panel [type='checkbox']:checked ~ * {
|
||||
/* this needs to autocalculate */
|
||||
min-height: 143px;
|
||||
max-height: 143px;
|
||||
}
|
||||
%menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] {
|
||||
display: block;
|
||||
}
|
||||
/**/
|
||||
%menu-panel dl {
|
||||
padding: 0.9em 1em;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
@import './skin';
|
||||
@import './layout';
|
||||
%with-popover-menu > input {
|
||||
%with-popover-menu > [type='checkbox'] {
|
||||
@extend %popover-menu;
|
||||
}
|
||||
%popover-menu {
|
||||
@extend %display-toggle-siblings;
|
||||
}
|
||||
%popover-menu + label + div {
|
||||
@extend %popover-menu-panel;
|
||||
}
|
||||
%popover-menu + label > * {
|
||||
@extend %toggle-button;
|
||||
}
|
||||
%more-popover-menu-panel,
|
||||
%popover-menu + label + div {
|
||||
@extend %popover-menu-panel;
|
||||
}
|
||||
%popover-menu-panel {
|
||||
@extend %menu-panel;
|
||||
}
|
||||
|
|
|
@ -1,56 +1,12 @@
|
|||
%with-popover-menu {
|
||||
position: relative;
|
||||
}
|
||||
%with-popover-menu > [type='checkbox'] {
|
||||
@extend %popover-menu;
|
||||
}
|
||||
%more-popover-menu {
|
||||
@extend %display-toggle-siblings;
|
||||
}
|
||||
%more-popover-menu + label > * {
|
||||
@extend %toggle-button;
|
||||
}
|
||||
%more-popover-menu-panel {
|
||||
overflow: hidden;
|
||||
width: 192px;
|
||||
}
|
||||
%more-popover-menu + label + div {
|
||||
@extend %more-popover-menu-panel;
|
||||
}
|
||||
%more-popover-menu-panel:not(.above) {
|
||||
top: 48px;
|
||||
}
|
||||
%more-popover-menu-panel:not(.left) {
|
||||
right: 10px;
|
||||
}
|
||||
%more-popover-menu-panel li [role='menu'] {
|
||||
display: none;
|
||||
}
|
||||
%more-popover-menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] {
|
||||
display: block;
|
||||
}
|
||||
%popover-menu {
|
||||
@extend %display-toggle-siblings;
|
||||
}
|
||||
%popover-menu + label > * {
|
||||
@extend %toggle-button;
|
||||
}
|
||||
%popover-menu-panel {
|
||||
@extend %menu-panel;
|
||||
width: 192px;
|
||||
}
|
||||
%popover-menu + label + div {
|
||||
@extend %popover-menu-panel;
|
||||
}
|
||||
%popover-menu-panel:not(.above) {
|
||||
top: 38px;
|
||||
}
|
||||
%popover-menu-panel:not(.left) {
|
||||
right: 10px;
|
||||
}
|
||||
%popover-menu-panel li [role='menu'] {
|
||||
display: none;
|
||||
}
|
||||
%popover-menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] {
|
||||
display: block;
|
||||
right: 5px;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,3 @@
|
|||
height: 16px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
%more-popover-menu + label > *::after {
|
||||
@extend %with-more-horizontal-icon, %as-pseudo;
|
||||
opacity: 0.7;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
%more-popover-menu + label > * {
|
||||
font-size: 0;
|
||||
background-color: $transparent;
|
||||
}
|
||||
|
|
|
@ -10,28 +10,23 @@
|
|||
.consul-gateway-service-list > ul > li:not(:first-child),
|
||||
.consul-service-instance-list > ul > li:not(:first-child),
|
||||
.consul-service-list > ul > li:not(:first-child),
|
||||
.consul-token-list > ul > li:not(:first-child) {
|
||||
.consul-token-list > ul > li:not(:first-child),
|
||||
.consul-policy-list > ul > li:not(:first-child),
|
||||
.consul-role-list > ul > li:not(:first-child) {
|
||||
@extend %with-composite-row-intent;
|
||||
}
|
||||
/*TODO: This hides the icons-less dt's in the below lists as */
|
||||
/* they don't have tooltips */
|
||||
.consul-token-list > ul > li:not(:first-child) dt {
|
||||
.consul-token-list > ul > li:not(:first-child) dt,
|
||||
.consul-policy-list > ul li:not(:first-child) dl:not(.datacenter) dt,
|
||||
.consul-role-list > ul > li:not(:first-child) dt {
|
||||
display: none;
|
||||
}
|
||||
/* TODO: the service list has a 1px offset */
|
||||
.consul-policy-list dl.datacenter dt,
|
||||
.consul-service-list li > div:first-child > dl:first-child dd {
|
||||
margin-top: 1px;
|
||||
}
|
||||
.proxy-exposed-paths tbody tr {
|
||||
cursor: default !important;
|
||||
}
|
||||
.proxy-exposed-paths tbody tr:hover {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.proxy-exposed-paths tbody tr .combined-address button:hover {
|
||||
// In this case we do not need a background on the icon
|
||||
background-color: $transparent !important;
|
||||
}
|
||||
.proxy-exposed-paths > ul,
|
||||
.proxy-upstreams > ul {
|
||||
border-top: 1px solid $gray-200;
|
||||
|
|
|
@ -33,9 +33,12 @@
|
|||
margin-right: 3px;
|
||||
}
|
||||
%composite-row-detail .policy-management::before {
|
||||
margin-right: 3px;
|
||||
}
|
||||
%composite-row-detail .policy-management::before,
|
||||
%composite-row-header .policy-management dd::before {
|
||||
@extend %with-star-fill-mask, %as-pseudo;
|
||||
background-color: var(--brand-600);
|
||||
margin-right: 3px;
|
||||
}
|
||||
// Health Checks
|
||||
%composite-row-detail li.passing::before,
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
.more-popover-menu > [type='checkbox'] {
|
||||
.more-popover-menu {
|
||||
@extend %more-popover-menu;
|
||||
}
|
||||
%more-popover-menu-panel [type='checkbox']:checked ~ * {
|
||||
/* this needs to autocalculate */
|
||||
min-height: 143px;
|
||||
max-height: 143px;
|
||||
%more-popover-menu {
|
||||
@extend %with-popover-menu;
|
||||
}
|
||||
%more-popover-menu-panel [id$='logout']:checked ~ * {
|
||||
/* this needs to autocalculate */
|
||||
min-height: 183px;
|
||||
max-height: 183px;
|
||||
%more-popover-menu > [type='checkbox'] + label {
|
||||
@extend %more-popover-menu-trigger;
|
||||
}
|
||||
%more-popover-menu-panel [id$='delete']:checked ~ ul label[for$='delete'] + [role='menu'],
|
||||
%more-popover-menu-panel [id$='logout']:checked ~ ul label[for$='logout'] + [role='menu'],
|
||||
%more-popover-menu-panel [id$='use']:checked ~ ul label[for$='use'] + [role='menu'] {
|
||||
/* This gives the trigger a slightly larger invisible hit area */
|
||||
%more-popover-menu-trigger {
|
||||
padding: 7px;
|
||||
display: block;
|
||||
}
|
||||
%more-popover-menu-trigger > * {
|
||||
font-size: 0;
|
||||
background-color: $transparent;
|
||||
padding: 0;
|
||||
}
|
||||
%more-popover-menu-trigger > *::after {
|
||||
@extend %with-more-horizontal-mask, %as-pseudo;
|
||||
background-color: $gray-900;
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -2,44 +2,21 @@ td strong {
|
|||
@extend %pill;
|
||||
margin-right: 3px;
|
||||
}
|
||||
// For the moment pills with classes are iconed ones
|
||||
%pill:not([class]) {
|
||||
@extend %frame-gray-900;
|
||||
}
|
||||
%pill[class] {
|
||||
padding-left: 0;
|
||||
margin-right: 16px;
|
||||
}
|
||||
%pill[class]::before {
|
||||
@extend %as-pseudo;
|
||||
margin-right: 3px;
|
||||
}
|
||||
%pill.policy::before {
|
||||
@extend %with-file-fill-icon;
|
||||
opacity: 0.3;
|
||||
}
|
||||
%pill.policy-management::before {
|
||||
@extend %with-star-icon;
|
||||
}
|
||||
%pill.role::before {
|
||||
@extend %with-user-plain-icon;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
// TODO: These are related to the pill icons, but also to the tables
|
||||
// All of this icon assigning stuff should probably go in the eventual
|
||||
// refactored /components/icons.scss file
|
||||
|
||||
span.policy-management a::after {
|
||||
@extend %with-star-icon, %as-pseudo;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
span.policy-service-identity,
|
||||
span.policy-node-identity,
|
||||
.consul-external-source,
|
||||
.consul-kind {
|
||||
@extend %reduced-pill;
|
||||
}
|
||||
span.policy-service-identity::before {
|
||||
width: 0;
|
||||
span.policy-service-identity::before,
|
||||
span.policy-node-identity::before {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
span.policy-node-identity::before {
|
||||
content: 'Node Identity: ';
|
||||
}
|
||||
span.policy-service-identity::before {
|
||||
content: 'Service Identity: ';
|
||||
}
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
%main-content table {
|
||||
@extend %table;
|
||||
}
|
||||
%table-actions > [type='checkbox'] {
|
||||
%table-actions {
|
||||
@extend %more-popover-menu;
|
||||
}
|
||||
%table-actions .confirmation-alert {
|
||||
@extend %confirmation-alert;
|
||||
overflow: visible;
|
||||
}
|
||||
%table-actions > [type='checkbox'] + label {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 15px;
|
||||
}
|
||||
%table-actions .menu-panel:not(.above) {
|
||||
top: 38px !important;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
/*TODO: Rename this to %app-view-brand-icon or similar */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<p class="notice policy-management"><strong>Management</strong> This global-management token is built into Consul's policy system. You can apply this special policy to tokens for full access. This policy is not editable or removeable, but can be ignored by not applying it to any tokens. Learn more in our <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl.html#builtin-policies" target="_blank" rel="noopener noreferrer">documentation</a>.</p>
|
||||
<div>
|
||||
<div class="definition-table">
|
||||
<dl>
|
||||
<dt>Name</dt>
|
||||
<dd>{{item.Name}}</dd>
|
||||
|
|
|
@ -40,66 +40,10 @@
|
|||
{{/if}}
|
||||
<ChangeableSet @dispatcher={{searchable 'policy' items}} @terms={{search}}>
|
||||
<BlockSlot @name="set" as |filtered|>
|
||||
<TabularCollection @items={{sort-by "CreateIndex:desc" "Name:asc" filtered}} as |item index|>
|
||||
<BlockSlot @name="header">
|
||||
<th>Name</th>
|
||||
<th>Datacenters</th>
|
||||
<th>Description</th>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="row">
|
||||
<td data-test-policy="{{item.Name}}">
|
||||
<a href={{href-to 'dc.acls.policies.edit' item.ID}} class={{if (eq (policy/typeof item) 'policy-management') 'is-management'}}>{{item.Name}}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{join ', ' (policy/datacenters item)}}
|
||||
</td>
|
||||
<td data-test-description>
|
||||
<p>{{item.Description}}</p>
|
||||
</td>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions" as |index change checked|>
|
||||
<PopoverMenu @expanded={{if (eq checked index) true false}} @onchange={{action change index}} @keyboardAccess={{false}}>
|
||||
<BlockSlot @name="trigger">
|
||||
More
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||
{{#if (eq (policy/typeof item) 'policy-management')}}
|
||||
<li role="none">
|
||||
<a role="menuitem" tabindex="-1" data-test-edit href={{href-to 'dc.acls.policies.edit' item.ID}}>View</a>
|
||||
</li>
|
||||
{{else}}
|
||||
|
||||
<li role="none">
|
||||
<a role="menuitem" tabindex="-1" data-test-edit href={{href-to 'dc.acls.policies.edit' item.ID}}>Edit</a>
|
||||
</li>
|
||||
<li role="none" class="dangerous">
|
||||
<label for={{confirm}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
||||
<div role="menu">
|
||||
<div class="confirmation-alert warning">
|
||||
<div>
|
||||
<header>
|
||||
Confirm Delete
|
||||
</header>
|
||||
<p>
|
||||
Are you sure you want to delete this policy?
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="dangerous">
|
||||
<button tabindex="-1" type="button" class="type-delete" onclick={{action send 'delete' item}}>Delete</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for={{confirm}}>Cancel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
</PopoverMenu>
|
||||
</BlockSlot>
|
||||
</TabularCollection>
|
||||
<ConsulPolicyList
|
||||
@items={{sort-by "CreateTime:desc" "Name:asc" filtered}}
|
||||
@ondelete={{action send 'delete'}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="empty">
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
|
|
|
@ -40,61 +40,10 @@
|
|||
{{/if}}
|
||||
<ChangeableSet @dispatcher={{searchable 'role' items}} @terms={{search}}>
|
||||
<BlockSlot @name="set" as |filtered|>
|
||||
<TabularCollection @items={{sort-by "CreateIndex:desc" "Name:asc" filtered}} as |item index|>
|
||||
<BlockSlot @name="header">
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Policies</th>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="row">
|
||||
<td data-test-role="{{item.Name}}">
|
||||
<a href={{href-to 'dc.acls.roles.edit' item.ID}}>{{item.Name}}</a>
|
||||
</td>
|
||||
<td data-test-description>
|
||||
<p>{{item.Description}}</p>
|
||||
</td>
|
||||
<td>
|
||||
{{#each item.Policies as |item|}}
|
||||
<strong data-test-policy class={{policy/typeof item}}>{{item.Name}}</strong>
|
||||
{{/each}}
|
||||
</td>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions" as |index change checked|>
|
||||
<PopoverMenu @expanded={{if (eq checked index) true false}} @onchange={{action change index}} @keyboardAccess={{false}}>
|
||||
<BlockSlot @name="trigger">
|
||||
More
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||
<li role="none">
|
||||
<a role="menuitem" tabindex="-1" href={{href-to 'dc.acls.roles.edit' item.ID}}>Edit</a>
|
||||
</li>
|
||||
<li role="none" class="dangerous">
|
||||
<label for={{confirm}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
||||
<div role="menu">
|
||||
<div class="confirmation-alert warning">
|
||||
<div>
|
||||
<header>
|
||||
Confirm Delete
|
||||
</header>
|
||||
<p>
|
||||
Are you sure you want to delete this role?
|
||||
</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="dangerous">
|
||||
<button tabindex="-1" type="button" class="type-delete" onclick={{action send 'delete' item}}>Delete</button>
|
||||
</li>
|
||||
<li>
|
||||
<label for={{confirm}}>Cancel</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</BlockSlot>
|
||||
</PopoverMenu>
|
||||
</BlockSlot>
|
||||
</TabularCollection>
|
||||
<ConsulRoleList
|
||||
@items={{sort-by "CreateTime:desc" "Name:asc" filtered}}
|
||||
@ondelete={{action send 'delete'}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="empty">
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
|
|
|
@ -77,7 +77,7 @@ Feature: dc / acls / tokens / index: ACL Token List
|
|||
s: Si-Search
|
||||
---
|
||||
And I see 1 token model
|
||||
And I see 1 token model with the serviceIdentity "Service Identity: Si-Search"
|
||||
And I see 1 token model with the serviceIdentity "Si-Search"
|
||||
Scenario: I see the legacy message if I have one legacy token
|
||||
Given 1 datacenter model with the value "dc-1"
|
||||
And 3 token models from yaml
|
||||
|
|
|
@ -33,8 +33,13 @@ import policyFormFactory from 'consul-ui/components/policy-form/pageobject';
|
|||
import policySelectorFactory from 'consul-ui/components/policy-selector/pageobject';
|
||||
import roleFormFactory from 'consul-ui/components/role-form/pageobject';
|
||||
import roleSelectorFactory from 'consul-ui/components/role-selector/pageobject';
|
||||
|
||||
import morePopoverMenuFactory from 'consul-ui/components/more-popover-menu/pageobject';
|
||||
|
||||
import tokenListFactory from 'consul-ui/components/token-list/pageobject';
|
||||
import consulTokenListFactory from 'consul-ui/components/consul-token-list/pageobject';
|
||||
import consulRoleListFactory from 'consul-ui/components/consul-role-list/pageobject';
|
||||
import consulPolicyListFactory from 'consul-ui/components/consul-policy-list/pageobject';
|
||||
import consulIntentionListFactory from 'consul-ui/components/consul-intention-list/pageobject';
|
||||
|
||||
// pages
|
||||
|
@ -86,8 +91,31 @@ const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text);
|
|||
const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm);
|
||||
const roleForm = roleFormFactory(submitable, cancelable, policySelector);
|
||||
const roleSelector = roleSelectorFactory(clickable, deletable, collection, alias, roleForm);
|
||||
|
||||
const morePopoverMenu = morePopoverMenuFactory(clickable);
|
||||
|
||||
const consulIntentionList = consulIntentionListFactory(collection, clickable, attribute, deletable);
|
||||
const consulTokenList = consulTokenListFactory(collection, clickable, attribute, text, deletable);
|
||||
const consulTokenList = consulTokenListFactory(
|
||||
collection,
|
||||
clickable,
|
||||
attribute,
|
||||
text,
|
||||
morePopoverMenu
|
||||
);
|
||||
const consulRoleList = consulRoleListFactory(
|
||||
collection,
|
||||
clickable,
|
||||
attribute,
|
||||
text,
|
||||
morePopoverMenu
|
||||
);
|
||||
const consulPolicyList = consulPolicyListFactory(
|
||||
collection,
|
||||
clickable,
|
||||
attribute,
|
||||
text,
|
||||
morePopoverMenu
|
||||
);
|
||||
|
||||
const page = pageFactory(clickable, attribute, is, authForm);
|
||||
|
||||
|
@ -115,22 +143,9 @@ export default {
|
|||
kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)),
|
||||
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)),
|
||||
acl: create(acl(visitable, submitable, deletable, cancelable, clickable)),
|
||||
policies: create(
|
||||
policies(
|
||||
visitable,
|
||||
deletable,
|
||||
creatable,
|
||||
clickable,
|
||||
attribute,
|
||||
collection,
|
||||
text,
|
||||
freetextFilter
|
||||
)
|
||||
),
|
||||
policies: create(policies(visitable, creatable, consulPolicyList, freetextFilter)),
|
||||
policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)),
|
||||
roles: create(
|
||||
roles(visitable, deletable, creatable, clickable, attribute, collection, text, freetextFilter)
|
||||
),
|
||||
roles: create(roles(visitable, creatable, consulRoleList, freetextFilter)),
|
||||
// TODO: This needs a policyList
|
||||
role: create(role(visitable, submitable, deletable, cancelable, policySelector, tokenList)),
|
||||
tokens: create(tokens(visitable, creatable, text, consulTokenList, freetextFilter)),
|
||||
|
|
|
@ -1,24 +1,7 @@
|
|||
export default function(
|
||||
visitable,
|
||||
deletable,
|
||||
creatable,
|
||||
clickable,
|
||||
attribute,
|
||||
collection,
|
||||
text,
|
||||
filter
|
||||
) {
|
||||
export default function(visitable, creatable, policies, filter) {
|
||||
return creatable({
|
||||
visit: visitable('/:dc/acls/policies'),
|
||||
policies: collection(
|
||||
'[data-test-tabular-row]',
|
||||
deletable({
|
||||
name: attribute('data-test-policy', '[data-test-policy]'),
|
||||
description: text('[data-test-description]'),
|
||||
policy: clickable('a'),
|
||||
actions: clickable('label'),
|
||||
})
|
||||
),
|
||||
policies: policies(),
|
||||
filter: filter(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,25 +1,8 @@
|
|||
export default function(
|
||||
visitable,
|
||||
deletable,
|
||||
creatable,
|
||||
clickable,
|
||||
attribute,
|
||||
collection,
|
||||
text,
|
||||
filter
|
||||
) {
|
||||
return creatable({
|
||||
export default function(visitable, creatable, roles, filter) {
|
||||
return {
|
||||
visit: visitable('/:dc/acls/roles'),
|
||||
roles: collection(
|
||||
'[data-test-tabular-row]',
|
||||
deletable({
|
||||
name: attribute('data-test-role', '[data-test-role]'),
|
||||
description: text('[data-test-description]'),
|
||||
policy: text('[data-test-policy].policy', { multiple: true }),
|
||||
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
|
||||
actions: clickable('label'),
|
||||
})
|
||||
),
|
||||
roles: roles(),
|
||||
filter: filter(),
|
||||
});
|
||||
...creatable(),
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue