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)}}
|
{{#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">
|
<BlockSlot @name="header">
|
||||||
{{#if (eq item.AccessorID token.AccessorID)}}
|
{{#if (eq item.AccessorID token.AccessorID)}}
|
||||||
<dl rel="me">
|
<dl rel="me">
|
||||||
<dd>
|
<dd>
|
||||||
<Tooltip>
|
<Tooltip @position="top-start">
|
||||||
Your token
|
Your token
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -19,50 +19,7 @@
|
||||||
{{if item.Local 'local' 'global' }}
|
{{if item.Local 'local' 'global' }}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{#let (policy/group item.Policies) as |policies|}}
|
<ConsulTokenRulesetList @item={{item}} />
|
||||||
{{#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}}
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Description</dt>
|
<dt>Description</dt>
|
||||||
<dd data-test-description>
|
<dd data-test-description>
|
||||||
|
@ -70,98 +27,86 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="actions">
|
<BlockSlot @name="actions" as |Actions|>
|
||||||
<div class="more-popover-menu">
|
<Actions as |Action|>
|
||||||
<PopoverMenu @expanded={{if (eq checked index) true false}} @onchange={{action change index}} @keyboardAccess={{false}} @submenus={{array "logout" "use" "delete"}}>
|
<Action data-test-edit-action @href={{href-to 'dc.acls.tokens.edit' item.AccessorID}}>
|
||||||
<BlockSlot @name="trigger">
|
<BlockSlot @name="label">
|
||||||
More
|
Edit
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
</Action>
|
||||||
<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))}}
|
{{#if (not (token/is-legacy item))}}
|
||||||
<li role="none">
|
<Action data-test-clone-action @onclick={{action onclone item}}>
|
||||||
<button role="menuitem" tabindex="-1" type="button" data-test-clone {{action onclone item}}>Duplicate</button>
|
<BlockSlot @name="label">
|
||||||
</li>
|
Duplicate
|
||||||
|
</BlockSlot>
|
||||||
|
</Action>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq item.AccessorID token.AccessorID)}}
|
{{#if (eq item.AccessorID token.AccessorID)}}
|
||||||
<li role="none" class="dangerous">
|
<Action data-test-logout-action class="dangerous" @onclick={{action onclone item}}>
|
||||||
<label for={{concat confirm 'logout'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-logout>Log out</label>
|
<BlockSlot @name="label">
|
||||||
<div role="menu">
|
Logout
|
||||||
<div class="confirmation-alert warning">
|
</BlockSlot>
|
||||||
<div>
|
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||||
<header>
|
<Confirmation class="warning">
|
||||||
|
<BlockSlot @name="header">
|
||||||
Confirm logout
|
Confirm logout
|
||||||
</header>
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="body">
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to stop using this ACL token? This will log you out.
|
Are you sure you want to stop using this ACL token? This will log you out.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</BlockSlot>
|
||||||
<ul>
|
<BlockSlot @name="confirm" as |Confirm|>
|
||||||
<li class="dangerous">
|
<Confirm>Logout</Confirm>
|
||||||
<button tabindex="-1" type="button" onclick={{action onlogout item}}>Logout</button>
|
</BlockSlot>
|
||||||
</li>
|
</Confirmation>
|
||||||
<li>
|
</BlockSlot>
|
||||||
<label for={{concat confirm 'logout'}}>Cancel</label>
|
</Action>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<li role="none">
|
<Action data-test-use-action @onclick={{action onuse item}}>
|
||||||
<label for={{concat confirm 'use'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-use>Use</label>
|
<BlockSlot @name="label">
|
||||||
<div role="menu">
|
Use
|
||||||
<div class="confirmation-alert warning">
|
</BlockSlot>
|
||||||
<div>
|
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||||
<header>
|
<Confirmation class="warning">
|
||||||
|
<BlockSlot @name="header">
|
||||||
Confirm use
|
Confirm use
|
||||||
</header>
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="body">
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to use this ACL token?
|
Are you sure you want to use this ACL token?
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</BlockSlot>
|
||||||
<ul>
|
<BlockSlot @name="confirm" as |Confirm|>
|
||||||
<li class="dangerous">
|
<Confirm>Use</Confirm>
|
||||||
<button data-test-confirm-use tabindex="-1" type="button" onclick={{action onuse item}}>Use</button>
|
</BlockSlot>
|
||||||
</li>
|
</Confirmation>
|
||||||
<li>
|
</BlockSlot>
|
||||||
<label for={{concat confirm 'use'}}>Cancel</label>
|
</Action>
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#unless (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)) }}
|
{{#if (not (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)))}}
|
||||||
<li role="none" class="dangerous">
|
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
||||||
<label for={{concat confirm 'delete'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
<BlockSlot @name="label">
|
||||||
<div role="menu">
|
Delete
|
||||||
<div class="confirmation-alert warning">
|
</BlockSlot>
|
||||||
<div>
|
<BlockSlot @name="confirmation" as |Confirmation|>
|
||||||
<header>
|
<Confirmation class="warning">
|
||||||
Confirm Delete
|
<BlockSlot @name="header">
|
||||||
</header>
|
Confirm delete
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="body">
|
||||||
<p>
|
<p>
|
||||||
Are you sure you want to delete this token?
|
Are you sure you want to delete this token?
|
||||||
</p>
|
</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>
|
</BlockSlot>
|
||||||
</PopoverMenu>
|
<BlockSlot @name="confirm" as |Confirm|>
|
||||||
</div>
|
<Confirm>Delete</Confirm>
|
||||||
|
</BlockSlot>
|
||||||
|
</Confirmation>
|
||||||
|
</BlockSlot>
|
||||||
|
</Action>
|
||||||
|
{{/if}}
|
||||||
|
</Actions>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
{{/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)', {
|
return collection('.consul-token-list li:not(:first-child)', {
|
||||||
id: attribute('data-test-token', '[data-test-token]'),
|
id: attribute('data-test-token', '[data-test-token]'),
|
||||||
description: text('[data-test-description]'),
|
description: text('[data-test-description]'),
|
||||||
|
@ -6,10 +6,6 @@ export default (collection, clickable, attribute, text, deletable) => () => {
|
||||||
role: text('[data-test-policy].role', { multiple: true }),
|
role: text('[data-test-policy].role', { multiple: true }),
|
||||||
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
|
serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }),
|
||||||
token: clickable('a'),
|
token: clickable('a'),
|
||||||
actions: clickable('label'),
|
...actions(['edit', 'delete', 'use', 'logout', 'clone']),
|
||||||
use: clickable('[data-test-use]'),
|
|
||||||
confirmUse: clickable('[data-test-confirm-use]'),
|
|
||||||
clone: clickable('[data-test-clone]'),
|
|
||||||
...deletable(),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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>
|
<li></li>
|
||||||
{{~#each _cells as |cell|~}}
|
{{~#each _cells as |cell|~}}
|
||||||
<li onclick={{action 'click'}} style={{{cell.style}}} class={{if (service/exists cell.item) 'linkable'}}>
|
<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="header"><div>{{yield cell.item cell.index}}</div></YieldSlot>
|
||||||
<YieldSlot @name="details"><div>{{yield cell.item cell.index checked (action "change")}}</div></YieldSlot>
|
<YieldSlot @name="details"><div>{{yield cell.item cell.index}}</div></YieldSlot>
|
||||||
<YieldSlot @name="actions"><div>{{yield cell.item cell.index checked (action "change")}}</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>
|
</li>
|
||||||
{{~/each~}}
|
{{~/each~}}
|
||||||
</EmberNativeScrollable>
|
</EmberNativeScrollable>
|
|
@ -1,15 +1,21 @@
|
||||||
{{yield}}
|
{{yield}}
|
||||||
|
{{#let (hash
|
||||||
|
change=(action "change")
|
||||||
|
) as |api|}}
|
||||||
<div class="menu-panel {{position}}">
|
<div class="menu-panel {{position}}">
|
||||||
<YieldSlot @name="controls">
|
<YieldSlot @name="controls">
|
||||||
{{yield}}
|
{{yield api}}
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
{{#yield-slot name="header"}}
|
{{#yield-slot name="header"}}
|
||||||
<div>{{yield}}</div>
|
<div>
|
||||||
|
{{yield api}}
|
||||||
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{/yield-slot}}
|
{{/yield-slot}}
|
||||||
<ul role="menu" ...attributes>
|
<ul role="menu" ...attributes>
|
||||||
<YieldSlot @name="menu">
|
<YieldSlot @name="menu">
|
||||||
{{yield}}
|
{{yield api}}
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{{/let}}
|
|
@ -1,7 +1,26 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
import Slotted from 'block-slots';
|
import Slotted from 'block-slots';
|
||||||
|
|
||||||
export default Component.extend(Slotted, {
|
export default Component.extend(Slotted, {
|
||||||
tagName: '',
|
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|>
|
<AriaMenu @keyboardAccess={{keyboardAccess}} as |change keypress ariaLabelledBy ariaControls ariaExpanded keypressClick|>
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
@checked={{if keyboardAccess ariaExpanded expanded}}
|
@checked={{if keyboardAccess ariaExpanded expanded}}
|
||||||
|
@ -7,25 +7,35 @@
|
||||||
<Ref @target={{this}} @name="toggle" @value={{api}} />
|
<Ref @target={{this}} @name="toggle" @value={{api}} />
|
||||||
<button type="button" aria-haspopup="menu" onkeydown={{keypress}} onclick={{this.toggle.click}} id={{ariaLabelledBy}} aria-controls={{ariaControls}}>
|
<button type="button" aria-haspopup="menu" onkeydown={{keypress}} onclick={{this.toggle.click}} id={{ariaLabelledBy}} aria-controls={{ariaControls}}>
|
||||||
<YieldSlot @name="trigger">
|
<YieldSlot @name="trigger">
|
||||||
{{yield}}
|
{{yield (hash
|
||||||
|
addSubmenu=(action 'addSubmenu')
|
||||||
|
removeSubmenu=(action 'removeSubmenu')
|
||||||
|
)}}
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
</button>
|
</button>
|
||||||
</ToggleButton>
|
</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">
|
<BlockSlot @name="controls">
|
||||||
<input type="checkbox" id={{concat 'popover-menu-' guid '-'}} />
|
<input type="checkbox" id={{concat 'popover-menu-' guid '-'}} />
|
||||||
{{#each submenus as |sub|}}
|
{{#each submenus as |sub|}}
|
||||||
<input type="checkbox" id={{concat 'popover-menu-' guid '-' sub}} />
|
<input type="checkbox" id={{concat 'popover-menu-' guid '-' sub}} onchange={{api.change}} />
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
{{#if hasHeader}}
|
{{#if hasHeader}}
|
||||||
<BlockSlot @name="header">
|
<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>
|
</BlockSlot>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<BlockSlot @name="menu">
|
<BlockSlot @name="menu">
|
||||||
<YieldSlot @name="menu" @params={{block-params (concat "popover-menu-" guid "-") send keypressClick this.toggle.click}}>
|
<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>
|
</YieldSlot>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</MenuPanel>
|
</MenuPanel>
|
||||||
|
|
|
@ -16,11 +16,22 @@ export default Component.extend(Slotted, {
|
||||||
init: function() {
|
init: function() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
this.guid = this.dom.guid(this);
|
this.guid = this.dom.guid(this);
|
||||||
|
this.submenus = [];
|
||||||
},
|
},
|
||||||
willRender: function() {
|
willRender: function() {
|
||||||
set(this, 'hasHeader', this._isRegistered('header'));
|
set(this, 'hasHeader', this._isRegistered('header'));
|
||||||
},
|
},
|
||||||
actions: {
|
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) {
|
change: function(e) {
|
||||||
if (!e.target.checked) {
|
if (!e.target.checked) {
|
||||||
[...this.dom.elements(`[id^=popover-menu-${this.guid}]`)].forEach(function($item) {
|
[...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';
|
const MANAGEMENT_ID = '00000000-0000-0000-0000-000000000001';
|
||||||
export function typeOf(params, hash) {
|
export function typeOf(params, hash) {
|
||||||
const item = params[0];
|
const item = params[0];
|
||||||
|
const template = get(item, 'template');
|
||||||
switch (true) {
|
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:
|
case get(item, 'ID') === MANAGEMENT_ID:
|
||||||
return 'policy-management';
|
return 'policy-management';
|
||||||
case typeof get(item, 'template') === 'undefined':
|
|
||||||
return 'role';
|
|
||||||
case get(item, 'template') !== '':
|
|
||||||
return 'policy-service-identity';
|
|
||||||
default:
|
default:
|
||||||
return 'policy';
|
return 'policy';
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
background-color: $yellow-050;
|
background-color: $yellow-050;
|
||||||
border-top-left-radius: $decor-radius-200;
|
border-top-left-radius: $decor-radius-200;
|
||||||
border-top-right-radius: $decor-radius-200;
|
border-top-right-radius: $decor-radius-200;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
%confirmation-alert > ul {
|
%confirmation-alert > ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
|
@ -4,15 +4,16 @@
|
||||||
%menu-panel [type='checkbox'] {
|
%menu-panel [type='checkbox'] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
%menu-panel [type='checkbox'] ~ * {
|
%menu-panel {
|
||||||
transition: transform 150ms, min-height 150ms, max-height 150ms;
|
overflow: hidden;
|
||||||
|
transition: min-height 150ms, max-height 150ms;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
%menu-panel [type='checkbox'] ~ * {
|
||||||
|
transition: transform 150ms;
|
||||||
|
}
|
||||||
%menu-panel [type='checkbox']:checked ~ * {
|
%menu-panel [type='checkbox']:checked ~ * {
|
||||||
transform: translateX(calc(-100% - 10px));
|
transform: translateX(calc(-100% - 10px));
|
||||||
/* this needs to autocalculate */
|
|
||||||
/* or be hardcoded */
|
|
||||||
/* min-height: 143px; */
|
|
||||||
}
|
}
|
||||||
%menu-panel [role='menuitem'] {
|
%menu-panel [role='menuitem'] {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -27,7 +28,19 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: calc(100% + 10px);
|
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 {
|
%menu-panel dl {
|
||||||
padding: 0.9em 1em;
|
padding: 0.9em 1em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
@import './skin';
|
@import './skin';
|
||||||
@import './layout';
|
@import './layout';
|
||||||
%with-popover-menu > input {
|
%with-popover-menu > [type='checkbox'] {
|
||||||
@extend %popover-menu;
|
@extend %popover-menu;
|
||||||
}
|
}
|
||||||
%popover-menu {
|
%popover-menu {
|
||||||
@extend %display-toggle-siblings;
|
@extend %display-toggle-siblings;
|
||||||
}
|
}
|
||||||
%popover-menu + label + div {
|
|
||||||
@extend %popover-menu-panel;
|
|
||||||
}
|
|
||||||
%popover-menu + label > * {
|
%popover-menu + label > * {
|
||||||
@extend %toggle-button;
|
@extend %toggle-button;
|
||||||
}
|
}
|
||||||
%more-popover-menu-panel,
|
%popover-menu + label + div {
|
||||||
|
@extend %popover-menu-panel;
|
||||||
|
}
|
||||||
%popover-menu-panel {
|
%popover-menu-panel {
|
||||||
@extend %menu-panel;
|
@extend %menu-panel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,12 @@
|
||||||
%with-popover-menu {
|
%with-popover-menu {
|
||||||
position: relative;
|
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 {
|
%popover-menu-panel {
|
||||||
@extend %menu-panel;
|
|
||||||
width: 192px;
|
width: 192px;
|
||||||
}
|
}
|
||||||
%popover-menu + label + div {
|
|
||||||
@extend %popover-menu-panel;
|
|
||||||
}
|
|
||||||
%popover-menu-panel:not(.above) {
|
%popover-menu-panel:not(.above) {
|
||||||
top: 38px;
|
top: 38px;
|
||||||
}
|
}
|
||||||
%popover-menu-panel:not(.left) {
|
%popover-menu-panel:not(.left) {
|
||||||
right: 10px;
|
right: 5px;
|
||||||
}
|
|
||||||
%popover-menu-panel li [role='menu'] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
%popover-menu-panel [id$='-']:first-child:checked ~ ul label[for$='-'] + [role='menu'] {
|
|
||||||
display: block;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,3 @@
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin-left: 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-gateway-service-list > ul > li:not(:first-child),
|
||||||
.consul-service-instance-list > ul > li:not(:first-child),
|
.consul-service-instance-list > ul > li:not(:first-child),
|
||||||
.consul-service-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;
|
@extend %with-composite-row-intent;
|
||||||
}
|
}
|
||||||
/*TODO: This hides the icons-less dt's in the below lists as */
|
/*TODO: This hides the icons-less dt's in the below lists as */
|
||||||
/* they don't have tooltips */
|
/* 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;
|
display: none;
|
||||||
}
|
}
|
||||||
/* TODO: the service list has a 1px offset */
|
/* 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 {
|
.consul-service-list li > div:first-child > dl:first-child dd {
|
||||||
margin-top: 1px;
|
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-exposed-paths > ul,
|
||||||
.proxy-upstreams > ul {
|
.proxy-upstreams > ul {
|
||||||
border-top: 1px solid $gray-200;
|
border-top: 1px solid $gray-200;
|
||||||
|
|
|
@ -33,9 +33,12 @@
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
%composite-row-detail .policy-management::before {
|
%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;
|
@extend %with-star-fill-mask, %as-pseudo;
|
||||||
background-color: var(--brand-600);
|
background-color: var(--brand-600);
|
||||||
margin-right: 3px;
|
|
||||||
}
|
}
|
||||||
// Health Checks
|
// Health Checks
|
||||||
%composite-row-detail li.passing::before,
|
%composite-row-detail li.passing::before,
|
||||||
|
|
|
@ -1,18 +1,24 @@
|
||||||
.more-popover-menu > [type='checkbox'] {
|
.more-popover-menu {
|
||||||
@extend %more-popover-menu;
|
@extend %more-popover-menu;
|
||||||
}
|
}
|
||||||
%more-popover-menu-panel [type='checkbox']:checked ~ * {
|
%more-popover-menu {
|
||||||
/* this needs to autocalculate */
|
@extend %with-popover-menu;
|
||||||
min-height: 143px;
|
|
||||||
max-height: 143px;
|
|
||||||
}
|
}
|
||||||
%more-popover-menu-panel [id$='logout']:checked ~ * {
|
%more-popover-menu > [type='checkbox'] + label {
|
||||||
/* this needs to autocalculate */
|
@extend %more-popover-menu-trigger;
|
||||||
min-height: 183px;
|
|
||||||
max-height: 183px;
|
|
||||||
}
|
}
|
||||||
%more-popover-menu-panel [id$='delete']:checked ~ ul label[for$='delete'] + [role='menu'],
|
/* This gives the trigger a slightly larger invisible hit area */
|
||||||
%more-popover-menu-panel [id$='logout']:checked ~ ul label[for$='logout'] + [role='menu'],
|
%more-popover-menu-trigger {
|
||||||
%more-popover-menu-panel [id$='use']:checked ~ ul label[for$='use'] + [role='menu'] {
|
padding: 7px;
|
||||||
display: block;
|
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;
|
@extend %pill;
|
||||||
margin-right: 3px;
|
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-service-identity,
|
||||||
|
span.policy-node-identity,
|
||||||
.consul-external-source,
|
.consul-external-source,
|
||||||
.consul-kind {
|
.consul-kind {
|
||||||
@extend %reduced-pill;
|
@extend %reduced-pill;
|
||||||
}
|
}
|
||||||
span.policy-service-identity::before {
|
span.policy-service-identity::before,
|
||||||
width: 0;
|
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 {
|
%main-content table {
|
||||||
@extend %table;
|
@extend %table;
|
||||||
}
|
}
|
||||||
%table-actions > [type='checkbox'] {
|
%table-actions {
|
||||||
@extend %more-popover-menu;
|
@extend %more-popover-menu;
|
||||||
}
|
overflow: visible;
|
||||||
%table-actions .confirmation-alert {
|
|
||||||
@extend %confirmation-alert;
|
|
||||||
}
|
}
|
||||||
%table-actions > [type='checkbox'] + label {
|
%table-actions > [type='checkbox'] + label {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
right: 5px;
|
||||||
right: 15px;
|
|
||||||
}
|
|
||||||
%table-actions .menu-panel:not(.above) {
|
|
||||||
top: 38px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*TODO: Rename this to %app-view-brand-icon or similar */
|
/*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>
|
<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>
|
<dl>
|
||||||
<dt>Name</dt>
|
<dt>Name</dt>
|
||||||
<dd>{{item.Name}}</dd>
|
<dd>{{item.Name}}</dd>
|
||||||
|
|
|
@ -40,66 +40,10 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<ChangeableSet @dispatcher={{searchable 'policy' items}} @terms={{search}}>
|
<ChangeableSet @dispatcher={{searchable 'policy' items}} @terms={{search}}>
|
||||||
<BlockSlot @name="set" as |filtered|>
|
<BlockSlot @name="set" as |filtered|>
|
||||||
<TabularCollection @items={{sort-by "CreateIndex:desc" "Name:asc" filtered}} as |item index|>
|
<ConsulPolicyList
|
||||||
<BlockSlot @name="header">
|
@items={{sort-by "CreateTime:desc" "Name:asc" filtered}}
|
||||||
<th>Name</th>
|
@ondelete={{action send 'delete'}}
|
||||||
<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>
|
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="empty">
|
<BlockSlot @name="empty">
|
||||||
<EmptyState @allowLogin={{true}}>
|
<EmptyState @allowLogin={{true}}>
|
||||||
|
|
|
@ -40,61 +40,10 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<ChangeableSet @dispatcher={{searchable 'role' items}} @terms={{search}}>
|
<ChangeableSet @dispatcher={{searchable 'role' items}} @terms={{search}}>
|
||||||
<BlockSlot @name="set" as |filtered|>
|
<BlockSlot @name="set" as |filtered|>
|
||||||
<TabularCollection @items={{sort-by "CreateIndex:desc" "Name:asc" filtered}} as |item index|>
|
<ConsulRoleList
|
||||||
<BlockSlot @name="header">
|
@items={{sort-by "CreateTime:desc" "Name:asc" filtered}}
|
||||||
<th>Name</th>
|
@ondelete={{action send 'delete'}}
|
||||||
<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>
|
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="empty">
|
<BlockSlot @name="empty">
|
||||||
<EmptyState @allowLogin={{true}}>
|
<EmptyState @allowLogin={{true}}>
|
||||||
|
|
|
@ -77,7 +77,7 @@ Feature: dc / acls / tokens / index: ACL Token List
|
||||||
s: Si-Search
|
s: Si-Search
|
||||||
---
|
---
|
||||||
And I see 1 token model
|
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
|
Scenario: I see the legacy message if I have one legacy token
|
||||||
Given 1 datacenter model with the value "dc-1"
|
Given 1 datacenter model with the value "dc-1"
|
||||||
And 3 token models from yaml
|
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 policySelectorFactory from 'consul-ui/components/policy-selector/pageobject';
|
||||||
import roleFormFactory from 'consul-ui/components/role-form/pageobject';
|
import roleFormFactory from 'consul-ui/components/role-form/pageobject';
|
||||||
import roleSelectorFactory from 'consul-ui/components/role-selector/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 tokenListFactory from 'consul-ui/components/token-list/pageobject';
|
||||||
import consulTokenListFactory from 'consul-ui/components/consul-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';
|
import consulIntentionListFactory from 'consul-ui/components/consul-intention-list/pageobject';
|
||||||
|
|
||||||
// pages
|
// pages
|
||||||
|
@ -86,8 +91,31 @@ const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text);
|
||||||
const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm);
|
const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm);
|
||||||
const roleForm = roleFormFactory(submitable, cancelable, policySelector);
|
const roleForm = roleFormFactory(submitable, cancelable, policySelector);
|
||||||
const roleSelector = roleSelectorFactory(clickable, deletable, collection, alias, roleForm);
|
const roleSelector = roleSelectorFactory(clickable, deletable, collection, alias, roleForm);
|
||||||
|
|
||||||
|
const morePopoverMenu = morePopoverMenuFactory(clickable);
|
||||||
|
|
||||||
const consulIntentionList = consulIntentionListFactory(collection, clickable, attribute, deletable);
|
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);
|
const page = pageFactory(clickable, attribute, is, authForm);
|
||||||
|
|
||||||
|
@ -115,22 +143,9 @@ export default {
|
||||||
kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)),
|
kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)),
|
||||||
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)),
|
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)),
|
||||||
acl: create(acl(visitable, submitable, deletable, cancelable, clickable)),
|
acl: create(acl(visitable, submitable, deletable, cancelable, clickable)),
|
||||||
policies: create(
|
policies: create(policies(visitable, creatable, consulPolicyList, freetextFilter)),
|
||||||
policies(
|
|
||||||
visitable,
|
|
||||||
deletable,
|
|
||||||
creatable,
|
|
||||||
clickable,
|
|
||||||
attribute,
|
|
||||||
collection,
|
|
||||||
text,
|
|
||||||
freetextFilter
|
|
||||||
)
|
|
||||||
),
|
|
||||||
policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)),
|
policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)),
|
||||||
roles: create(
|
roles: create(roles(visitable, creatable, consulRoleList, freetextFilter)),
|
||||||
roles(visitable, deletable, creatable, clickable, attribute, collection, text, freetextFilter)
|
|
||||||
),
|
|
||||||
// TODO: This needs a policyList
|
// TODO: This needs a policyList
|
||||||
role: create(role(visitable, submitable, deletable, cancelable, policySelector, tokenList)),
|
role: create(role(visitable, submitable, deletable, cancelable, policySelector, tokenList)),
|
||||||
tokens: create(tokens(visitable, creatable, text, consulTokenList, freetextFilter)),
|
tokens: create(tokens(visitable, creatable, text, consulTokenList, freetextFilter)),
|
||||||
|
|
|
@ -1,24 +1,7 @@
|
||||||
export default function(
|
export default function(visitable, creatable, policies, filter) {
|
||||||
visitable,
|
|
||||||
deletable,
|
|
||||||
creatable,
|
|
||||||
clickable,
|
|
||||||
attribute,
|
|
||||||
collection,
|
|
||||||
text,
|
|
||||||
filter
|
|
||||||
) {
|
|
||||||
return creatable({
|
return creatable({
|
||||||
visit: visitable('/:dc/acls/policies'),
|
visit: visitable('/:dc/acls/policies'),
|
||||||
policies: collection(
|
policies: policies(),
|
||||||
'[data-test-tabular-row]',
|
|
||||||
deletable({
|
|
||||||
name: attribute('data-test-policy', '[data-test-policy]'),
|
|
||||||
description: text('[data-test-description]'),
|
|
||||||
policy: clickable('a'),
|
|
||||||
actions: clickable('label'),
|
|
||||||
})
|
|
||||||
),
|
|
||||||
filter: filter(),
|
filter: filter(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,8 @@
|
||||||
export default function(
|
export default function(visitable, creatable, roles, filter) {
|
||||||
visitable,
|
return {
|
||||||
deletable,
|
|
||||||
creatable,
|
|
||||||
clickable,
|
|
||||||
attribute,
|
|
||||||
collection,
|
|
||||||
text,
|
|
||||||
filter
|
|
||||||
) {
|
|
||||||
return creatable({
|
|
||||||
visit: visitable('/:dc/acls/roles'),
|
visit: visitable('/:dc/acls/roles'),
|
||||||
roles: collection(
|
roles: roles(),
|
||||||
'[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'),
|
|
||||||
})
|
|
||||||
),
|
|
||||||
filter: filter(),
|
filter: filter(),
|
||||||
});
|
...creatable(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue