ui: Add 'Search Across' for finer grained searching (#9282)
This commit is contained in:
parent
91d5d6c586
commit
7d8ea08da7
|
@ -0,0 +1,122 @@
|
||||||
|
<div
|
||||||
|
class="consul-acl-list"
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<TabularCollection
|
||||||
|
@items={{@items}}
|
||||||
|
as |item index|
|
||||||
|
>
|
||||||
|
<BlockSlot @name="header">
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Type</th>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="row">
|
||||||
|
<td data-test-acl={{item.Name}}>
|
||||||
|
<a href={{href-to 'dc.acls.edit' item.ID}}>{{item.Name}}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{#if (eq item.Type 'management')}}
|
||||||
|
<strong>{{item.Type}}</strong>
|
||||||
|
{{else}}
|
||||||
|
<span>{{item.Type}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</td>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="actions" as |index change checked|>
|
||||||
|
<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.edit' item.ID}}>Edit</a>
|
||||||
|
</li>
|
||||||
|
{{#if (eq item.ID token.SecretID) }}
|
||||||
|
<li role="none">
|
||||||
|
<label for={{concat confirm 'logout'}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-logout>Stop using</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 send 'logout' 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
|
||||||
|
{{on 'click' (fn @onuse item)}}
|
||||||
|
data-test-confirm-use
|
||||||
|
tabindex="-1"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Use
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<label for={{concat confirm 'use'}}>Cancel</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{/if}}
|
||||||
|
<li role="none">
|
||||||
|
<button role="menuitem" tabindex="-1" type="button" data-test-clone {{action @onclone item}}>Duplicate</button>
|
||||||
|
</li>
|
||||||
|
{{# if (not-eq item.ID 'anonymous') }}
|
||||||
|
<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>
|
||||||
|
{{/if}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverMenu>
|
||||||
|
</BlockSlot>
|
||||||
|
</TabularCollection>
|
||||||
|
</div>
|
|
@ -0,0 +1,59 @@
|
||||||
|
<form
|
||||||
|
class="consul-acl-search-bar filter-bar"
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<div class="search">
|
||||||
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="filters">
|
||||||
|
<PopoverSelect
|
||||||
|
@position="left"
|
||||||
|
@onchange={{action @onfilter.kind}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Type
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="management" @selected={{contains 'management' @filter.kinds}}>Management</Option>
|
||||||
|
<Option @value="client" @selected={{contains 'service' @filter.kinds}}>Client</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</div>
|
||||||
|
<div class="sort">
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-sort"
|
||||||
|
data-test-sort-control
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onsort}}
|
||||||
|
@multiple={{false}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
{{#let (from-entries (array
|
||||||
|
(array "Name:asc" "A to Z")
|
||||||
|
(array "Name:desc" "Z to A")
|
||||||
|
))
|
||||||
|
as |selectable|
|
||||||
|
}}
|
||||||
|
{{get selectable @sort}}
|
||||||
|
{{/let}}
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -3,15 +3,8 @@
|
||||||
...attributes
|
...attributes
|
||||||
{{did-update this.updateCRDManagement @items}}
|
{{did-update this.updateCRDManagement @items}}
|
||||||
>
|
>
|
||||||
<DataWriter
|
{{yield (hash
|
||||||
@sink={{concat '/' @dc '/' @nspace '/intention/'}}
|
Table=(component 'consul/intention/list/table' delete=@delete items=this.items)
|
||||||
@type="intention"
|
|
||||||
@ondelete={{action @ondelete}}
|
|
||||||
as |writer|>
|
|
||||||
<BlockSlot @name="content">
|
|
||||||
|
|
||||||
{{#let (hash
|
|
||||||
Table=(component 'consul/intention/list/table' delete=writer.delete items=this.items)
|
|
||||||
CheckNotice=(if this.checkedItem
|
CheckNotice=(if this.checkedItem
|
||||||
(component 'consul/intention/list/check' item=this.checkedItem)
|
(component 'consul/intention/list/check' item=this.checkedItem)
|
||||||
''
|
''
|
||||||
|
@ -20,15 +13,5 @@
|
||||||
(component 'consul/intention/notice/custom-resource')
|
(component 'consul/intention/notice/custom-resource')
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
) as |api|}}
|
)}}
|
||||||
|
|
||||||
{{#if (gt this.items.length 0)}}
|
|
||||||
{{yield api to="idle"}}
|
|
||||||
{{else}}
|
|
||||||
{{yield api to="empty"}}
|
|
||||||
{{/if}}
|
|
||||||
{{/let}}
|
|
||||||
|
|
||||||
</BlockSlot>
|
|
||||||
</DataWriter>
|
|
||||||
</div>
|
</div>
|
|
@ -5,13 +5,8 @@ import { tracked } from '@glimmer/tracking';
|
||||||
import { sort } from '@ember/object/computed';
|
import { sort } from '@ember/object/computed';
|
||||||
|
|
||||||
export default class ConsulIntentionList extends Component {
|
export default class ConsulIntentionList extends Component {
|
||||||
@service('filter') filter;
|
|
||||||
@service('sort') sort;
|
|
||||||
@service('search') search;
|
|
||||||
@service('repository/intention') repo;
|
@service('repository/intention') repo;
|
||||||
|
|
||||||
@sort('searched', 'comparator') sorted;
|
|
||||||
|
|
||||||
@tracked isManagedByCRDs;
|
@tracked isManagedByCRDs;
|
||||||
|
|
||||||
constructor(owner, args) {
|
constructor(owner, args) {
|
||||||
|
@ -19,25 +14,11 @@ export default class ConsulIntentionList extends Component {
|
||||||
this.updateCRDManagement(args.items);
|
this.updateCRDManagement(args.items);
|
||||||
}
|
}
|
||||||
get items() {
|
get items() {
|
||||||
return this.sorted;
|
return this.args.items || [];
|
||||||
}
|
|
||||||
get filtered() {
|
|
||||||
const predicate = this.filter.predicate('intention');
|
|
||||||
return this.args.items.filter(predicate(this.args.filters));
|
|
||||||
}
|
|
||||||
get searched() {
|
|
||||||
if (typeof this.args.search === 'undefined') {
|
|
||||||
return this.filtered;
|
|
||||||
}
|
|
||||||
const predicate = this.search.predicate('intention');
|
|
||||||
return this.filtered.filter(predicate(this.args.search));
|
|
||||||
}
|
|
||||||
get comparator() {
|
|
||||||
return [this.args.sort];
|
|
||||||
}
|
}
|
||||||
get checkedItem() {
|
get checkedItem() {
|
||||||
if (this.searched.length === 1) {
|
if (this.items.length === 1 && this.args.check) {
|
||||||
return this.searched[0].SourceName === this.args.search ? this.searched[0] : null;
|
return this.items[0].SourceName === this.args.check ? this.items[0] : null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,48 @@
|
||||||
class="consul-intention-search-bar filter-bar"
|
class="consul-intention-search-bar filter-bar"
|
||||||
...attributes
|
...attributes
|
||||||
>
|
>
|
||||||
<FreetextFilter
|
<div class="search">
|
||||||
@onsearch={{action onsearch}}
|
<FreetextFilter
|
||||||
@value={{search}}
|
@onsearch={{action @onsearch}}
|
||||||
@placeholder="Search"
|
@value={{@search}}
|
||||||
/>
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="SourceName" @selected={{contains 'SourceName' @filter.searchproperties}}>Source Name</Option>
|
||||||
|
<Option @value="DestinationName" @selected={{contains 'DestinationName' @filter.searchproperties}}>Destination Name</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.access}}
|
@onchange={{action @onfilter.access}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
<span>
|
<span>
|
||||||
Intent
|
Permission
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option class="value-allow" @value="allow" @selected={{contains 'allow' filter.accesses}}>Allow</Option>
|
<Option class="value-allow" @value="allow" @selected={{contains 'allow' @filter.accesses}}>Allow</Option>
|
||||||
<Option class="value-deny" @value="deny" @selected={{contains 'deny' filter.accesses}}>Deny</Option>
|
<Option class="value-deny" @value="deny" @selected={{contains 'deny' @filter.accesses}}>Deny</Option>
|
||||||
<Option class="value-" @value="app-aware" @selected={{contains 'app-aware' filter.accesses}}>App aware</Option>
|
<Option class="value-" @value="app-aware" @selected={{contains 'app-aware' @filter.accesses}}>App aware</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
|
@ -32,7 +53,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -49,27 +70,27 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Permission">
|
<Optgroup @label="Permission">
|
||||||
<Option @value="Action:asc" @selected={{eq "Action:asc" sort}}>Allow to Deny</Option>
|
<Option @value="Action:asc" @selected={{eq "Action:asc" @sort}}>Allow to Deny</Option>
|
||||||
<Option @value="Action:desc" @selected={{eq "Action:desc" sort}}>Deny to Allow</Option>
|
<Option @value="Action:desc" @selected={{eq "Action:desc" @sort}}>Deny to Allow</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Source">
|
<Optgroup @label="Source">
|
||||||
<Option @value="SourceName:asc" @selected={{eq "SourceName:asc" sort}}>A to Z</Option>
|
<Option @value="SourceName:asc" @selected={{eq "SourceName:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="SourceName:desc" @selected={{eq "SourceName:desc" sort}}>Z to A</Option>
|
<Option @value="SourceName:desc" @selected={{eq "SourceName:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Destination">
|
<Optgroup @label="Destination">
|
||||||
<Option @value="DestinationName:asc" @selected={{eq "DestinationName:asc" sort}}>A to Z</Option>
|
<Option @value="DestinationName:asc" @selected={{eq "DestinationName:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="DestinationName:desc" @selected={{eq "DestinationName:desc" sort}}>Z to A</Option>
|
<Option @value="DestinationName:desc" @selected={{eq "DestinationName:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Precedence">
|
<Optgroup @label="Precedence">
|
||||||
<Option @value="Precedence:asc" @selected={{eq "Precedence:asc" sort}}>Ascending</Option>
|
<Option @value="Precedence:asc" @selected={{eq "Precedence:asc" @sort}}>Ascending</Option>
|
||||||
<Option @value="Precedence:desc" @selected={{eq "Precedence:desc" sort}}>Descending</Option>
|
<Option @value="Precedence:desc" @selected={{eq "Precedence:desc" @sort}}>Descending</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,9 +1,12 @@
|
||||||
.consul-intention-search-bar {
|
.consul-intention-search-bar {
|
||||||
.value-allow button::before {
|
.value-allow button::before {
|
||||||
@extend %with-arrow-right-color-mask, %as-pseudo;
|
@extend %with-arrow-right-mask, %as-pseudo;
|
||||||
color: $green-500;
|
color: $green-500;
|
||||||
}
|
}
|
||||||
.value-deny button::before {
|
.value-deny button::before {
|
||||||
@extend %with-deny-color-icon, %as-pseudo;
|
@extend %with-deny-color-icon, %as-pseudo;
|
||||||
}
|
}
|
||||||
|
.value- button::before {
|
||||||
|
@extend %with-layers-mask, %as-pseudo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +1,56 @@
|
||||||
<DataWriter
|
<TabularCollection
|
||||||
@sink={{concat '/' dc '/' nspace '/kv/'}}
|
class="consul-kv-list"
|
||||||
@type="kv"
|
...attributes
|
||||||
@label="key"
|
@items={{@items}}
|
||||||
@ondelete={{action ondelete}}
|
as |item index|>
|
||||||
as |writer|>
|
<BlockSlot @name="header">
|
||||||
<BlockSlot @name="content">
|
<th>Name</th>
|
||||||
{{#if (gt items.length 0)}}
|
</BlockSlot>
|
||||||
<TabularCollection class="consul-kv-list" @items={{items}} as |item index|>
|
<BlockSlot @name="row">
|
||||||
<BlockSlot @name="header">
|
<td data-test-kv={{item.Key}} class={{if item.isFolder 'folder' 'file'}}>
|
||||||
<th>Name</th>
|
<a href={{href-to (if item.isFolder 'dc.kv.folder' 'dc.kv.edit') item.Key}}>{{right-trim (left-trim item.Key @parent.Key) '/'}}</a>
|
||||||
</BlockSlot>
|
</td>
|
||||||
<BlockSlot @name="row">
|
</BlockSlot>
|
||||||
<td data-test-kv={{item.Key}} class={{if item.isFolder 'folder' 'file' }}>
|
<BlockSlot @name="actions" as |index change checked|>
|
||||||
<a href={{href-to (if item.isFolder 'dc.kv.folder' 'dc.kv.edit') item.Key}}>{{right-trim (left-trim item.Key parent.Key) '/'}}</a>
|
<PopoverMenu @expanded={{if (eq checked index) true false}} @onchange={{action change index}} @keyboardAccess={{false}}>
|
||||||
</td>
|
<BlockSlot @name="trigger">
|
||||||
</BlockSlot>
|
More
|
||||||
<BlockSlot @name="actions" as |index change checked|>
|
</BlockSlot>
|
||||||
<PopoverMenu @expanded={{if (eq checked index) true false}} @onchange={{action change index}} @keyboardAccess={{false}}>
|
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
||||||
<BlockSlot @name="trigger">
|
<li role="none">
|
||||||
More
|
<a data-test-edit role="menuitem" tabindex="-1" href={{href-to (if item.isFolder 'dc.kv.folder' 'dc.kv.edit') item.Key}}>{{if item.isFolder 'View' 'Edit'}}</a>
|
||||||
</BlockSlot>
|
</li>
|
||||||
<BlockSlot @name="menu" as |confirm send keypressClick|>
|
<li role="none" class="dangerous">
|
||||||
<li role="none">
|
<label for={{confirm}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
||||||
<a data-test-edit role="menuitem" tabindex="-1" href={{href-to (if item.isFolder 'dc.kv.folder' 'dc.kv.edit') item.Key}}>{{if item.isFolder 'View' 'Edit'}}</a>
|
<div role="menu">
|
||||||
</li>
|
<div class="confirmation-alert warning">
|
||||||
<li role="none" class="dangerous">
|
<div>
|
||||||
<label for={{confirm}} role="menuitem" tabindex="-1" onkeypress={{keypressClick}} data-test-delete>Delete</label>
|
<header>
|
||||||
<div role="menu">
|
Confirm Delete
|
||||||
<div class="confirmation-alert warning">
|
</header>
|
||||||
<div>
|
<p>
|
||||||
<header>
|
Are you sure you want to delete this key?
|
||||||
Confirm Delete
|
</p>
|
||||||
</header>
|
</div>
|
||||||
<p>
|
<ul>
|
||||||
Are you sure you want to delete this key?
|
<li class="dangerous">
|
||||||
</p>
|
<button
|
||||||
</div>
|
tabindex="-1"
|
||||||
<ul>
|
type="button"
|
||||||
<li class="dangerous">
|
class="type-delete"
|
||||||
<button tabindex="-1" type="button" class="type-delete" onclick={{queue (action change) (action writer.delete item)}}>Delete</button>
|
onclick={{queue (action change) (action @delete item)}}
|
||||||
</li>
|
>
|
||||||
<li>
|
Delete
|
||||||
<label for={{confirm}}>Cancel</label>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
<li>
|
||||||
</div>
|
<label for={{confirm}}>Cancel</label>
|
||||||
</div>
|
</li>
|
||||||
</li>
|
</ul>
|
||||||
</BlockSlot>
|
</div>
|
||||||
</PopoverMenu>
|
</div>
|
||||||
</BlockSlot>
|
</li>
|
||||||
</TabularCollection>
|
</BlockSlot>
|
||||||
{{else}}
|
</PopoverMenu>
|
||||||
{{yield}}
|
</BlockSlot>
|
||||||
{{/if}}
|
</TabularCollection>
|
||||||
</BlockSlot>
|
|
||||||
</DataWriter>
|
|
|
@ -1,6 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
ondelete: function() {},
|
|
||||||
});
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
<form
|
||||||
|
class="consul-kv-search-bar filter-bar"
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<div class="search">
|
||||||
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="filters">
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-kind"
|
||||||
|
@position="left"
|
||||||
|
@onchange={{action @onfilter.kind}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Type
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="folder" @selected={{contains 'folder' @filter.kinds}}>Folder</Option>
|
||||||
|
<Option @value="key" @selected={{contains 'key' @filter.kinds}}>Key</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</div>
|
||||||
|
<div class="sort">
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-sort"
|
||||||
|
data-test-sort-control
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onsort}}
|
||||||
|
@multiple={{false}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
{{#let (from-entries (array
|
||||||
|
(array "Key:asc" "A to Z")
|
||||||
|
(array "Key:desc" "Z to A")
|
||||||
|
(array "Kind:asc" "Folders to Keys")
|
||||||
|
(array "Kind:desc" "Keys to Folders")
|
||||||
|
))
|
||||||
|
as |selectable|
|
||||||
|
}}
|
||||||
|
{{get selectable @sort}}
|
||||||
|
{{/let}}
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Optgroup @label="Name">
|
||||||
|
<Option @value="Key:asc" @selected={{eq "Key:asc" @sort}}>A to Z</Option>
|
||||||
|
<Option @value="Key:desc" @selected={{eq "Key:desc" @sort}}>Z to A</Option>
|
||||||
|
</Optgroup>
|
||||||
|
<Optgroup @label="Type">
|
||||||
|
<Option @value="Kind:asc" @selected={{eq "Kind:asc" @sort}}>Folders to Keys</Option>
|
||||||
|
<Option @value="Kind:desc" @selected={{eq "Kind:desc" @sort}}>Keys to Folders</Option>
|
||||||
|
</Optgroup>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -1,5 +1,7 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} class="consul-node-list" as |item index|>
|
class="consul-node-list"
|
||||||
|
@items={{@items}}
|
||||||
|
as |item index|>
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="header">
|
||||||
<dl class={{item.Status}}>
|
<dl class={{item.Status}}>
|
||||||
<dt>
|
<dt>
|
||||||
|
@ -24,8 +26,8 @@
|
||||||
</a>
|
</a>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="details">
|
<BlockSlot @name="details">
|
||||||
{{#if (eq item.Address leader.Address)}}
|
{{#if (eq item.Address @leader.Address)}}
|
||||||
<span class="leader" data-test-leader={{leader.Address}}>Leader</span>
|
<span class="leader" data-test-leader={{@leader.Address}}>Leader</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (gt item.Services.length 0)}}
|
{{#if (gt item.Services.length 0)}}
|
||||||
<span>
|
<span>
|
||||||
|
@ -46,4 +48,3 @@
|
||||||
</dl>
|
</dl>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,14 +1,39 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-node-list filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Node" @selected={{contains 'Node' @filter.searchproperties}}>Node Name</Option>
|
||||||
|
<Option @value="Address" @selected={{contains 'Address' @filter.searchproperties}}>Address</Option>
|
||||||
|
<Option @value="Meta" @selected={{contains 'Meta' @filter.searchproperties}}>Node Meta</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-status"
|
class="type-status"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.status}}
|
@onchange={{action @onfilter.status}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -18,10 +43,10 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option class="value-passing" @value="passing" @selected={{contains 'passing' filter.statuses}}>Passing</Option>
|
<Option class="value-passing" @value="passing" @selected={{contains 'passing' @filter.statuses}}>Passing</Option>
|
||||||
<Option class="value-warning" @value="warning" @selected={{contains 'warning' filter.statuses}}>Warning</Option>
|
<Option class="value-warning" @value="warning" @selected={{contains 'warning' @filter.statuses}}>Warning</Option>
|
||||||
<Option class="value-critical" @value="critical" @selected={{contains 'critical' filter.statuses}}>Failing</Option>
|
<Option class="value-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' filter.statuses}}>No checks</Option>
|
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
|
@ -31,7 +56,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -44,19 +69,19 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Health Status">
|
<Optgroup @label="Health Status">
|
||||||
<Option @value="Status:asc" @selected={{eq "Status:asc" sort}}>Unhealthy to Healthy</Option>
|
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort}}>Unhealthy to Healthy</Option>
|
||||||
<Option @value="Status:desc" @selected={{eq "Status:desc" sort}}>Healthy to Unhealthy</Option>
|
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort}}>Healthy to Unhealthy</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Service Name">
|
<Optgroup @label="Service Name">
|
||||||
<Option @value="Node:asc" @selected={{eq "Node:asc" sort}}>A to Z</Option>
|
<Option @value="Node:asc" @selected={{eq "Node:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Node:desc" @selected={{eq "Node:desc" sort}}>Z to A</Option>
|
<Option @value="Node:desc" @selected={{eq "Node:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,59 +1,60 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} @linkable={{action "isLinkable"}} class="consul-nspace-list" as |item|>
|
class="consul-nspace-list"
|
||||||
<BlockSlot @name="header">
|
...attributes
|
||||||
{{#if item.DeletedAt}}
|
@items={{@items}}
|
||||||
<p>
|
@linkable={{action this.isLinkable}}
|
||||||
Deleting {{item.Name}}...
|
as |item|>
|
||||||
</p>
|
<BlockSlot @name="header">
|
||||||
{{else}}
|
{{#if item.DeletedAt}}
|
||||||
<a data-test-nspace={{item.Name}} href={{href-to 'dc.nspaces.edit' item.Name}}>{{item.Name}}</a>
|
<p>
|
||||||
{{/if}}
|
Deleting {{item.Name}}...
|
||||||
</BlockSlot>
|
</p>
|
||||||
<BlockSlot @name="details">
|
|
||||||
<dl>
|
|
||||||
<dt>Description</dt>
|
|
||||||
<dd data-test-description>
|
|
||||||
{{item.Description}}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
{{#if (env 'CONSUL_ACLS_ENABLED')}}
|
|
||||||
<Consul::Token::Ruleset::List @item={{item}} />
|
|
||||||
{{/if}}
|
|
||||||
</BlockSlot>
|
|
||||||
<BlockSlot @name="actions" as |Actions|>
|
|
||||||
{{#if (not item.DeletedAt)}}
|
|
||||||
<Actions as |Action|>
|
|
||||||
<Action data-test-edit-action @href={{href-to 'dc.nspaces.edit' item.Name}}>
|
|
||||||
<BlockSlot @name="label">
|
|
||||||
Edit
|
|
||||||
</BlockSlot>
|
|
||||||
</Action>
|
|
||||||
{{#if (not-eq item.Name 'default') }}
|
|
||||||
<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 namespace?
|
|
||||||
</p>
|
|
||||||
</BlockSlot>
|
|
||||||
<BlockSlot @name="confirm" as |Confirm|>
|
|
||||||
<Confirm>Delete</Confirm>
|
|
||||||
</BlockSlot>
|
|
||||||
</Confirmation>
|
|
||||||
</BlockSlot>
|
|
||||||
</Action>
|
|
||||||
{{/if}}
|
|
||||||
</Actions>
|
|
||||||
{{/if}}
|
|
||||||
</BlockSlot>
|
|
||||||
</ListCollection>
|
|
||||||
{{else}}
|
{{else}}
|
||||||
{{yield to="empty"}}
|
<a data-test-nspace={{item.Name}} href={{href-to 'dc.nspaces.edit' item.Name}}>{{item.Name}}</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="details">
|
||||||
|
<dl>
|
||||||
|
<dt>Description</dt>
|
||||||
|
<dd data-test-description>
|
||||||
|
{{item.Description}}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
{{#if (env 'CONSUL_ACLS_ENABLED')}}
|
||||||
|
<Consul::Token::Ruleset::List @item={{item}} />
|
||||||
|
{{/if}}
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="actions" as |Actions|>
|
||||||
|
{{#if (not item.DeletedAt)}}
|
||||||
|
<Actions as |Action|>
|
||||||
|
<Action data-test-edit-action @href={{href-to 'dc.nspaces.edit' item.Name}}>
|
||||||
|
<BlockSlot @name="label">
|
||||||
|
Edit
|
||||||
|
</BlockSlot>
|
||||||
|
</Action>
|
||||||
|
{{#if (not-eq item.Name 'default') }}
|
||||||
|
<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 namespace?
|
||||||
|
</p>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="confirm" as |Confirm|>
|
||||||
|
<Confirm>Delete</Confirm>
|
||||||
|
</BlockSlot>
|
||||||
|
</Confirmation>
|
||||||
|
</BlockSlot>
|
||||||
|
</Action>
|
||||||
|
{{/if}}
|
||||||
|
</Actions>
|
||||||
|
{{/if}}
|
||||||
|
</BlockSlot>
|
||||||
|
</ListCollection>
|
|
@ -1,10 +1,8 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@glimmer/component';
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
|
||||||
export default Component.extend({
|
export default class ConsulNspaceList extends Component {
|
||||||
tagName: '',
|
isLinkable(item) {
|
||||||
actions: {
|
return !item.DeletedAt;
|
||||||
isLinkable: function(item) {
|
}
|
||||||
return !item.DeletedAt;
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,15 +1,41 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-nspace-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{contains 'Name' @filter.searchproperties}}>Name</Option>
|
||||||
|
<Option @value="Description" @selected={{contains 'Description' @filter.searchproperties}}>Description</Option>
|
||||||
|
<Option @value="Policy" @selected={{contains 'Policy' @filter.searchproperties}}>Policy</Option>
|
||||||
|
<Option @value="Role" @selected={{contains 'Role' @filter.searchproperties}}>Role</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="sort">
|
<div class="sort">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -20,15 +46,15 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Name">
|
<Optgroup @label="Name">
|
||||||
<Option @value="Name:asc" @selected={{eq "Name:asc" sort}}>A to Z</Option>
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Name:desc" @selected={{eq "Name:desc" sort}}>Z to A</Option>
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,5 +1,7 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} class="consul-policy-list" as |item|>
|
class="consul-policy-list"
|
||||||
|
@items={{@items}}
|
||||||
|
as |item|>
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="header">
|
||||||
{{#if (eq (policy/typeof item) 'policy-management')}}
|
{{#if (eq (policy/typeof item) 'policy-management')}}
|
||||||
<dl class="policy-management">
|
<dl class="policy-management">
|
||||||
|
@ -40,7 +42,7 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{#if (not-eq (policy/typeof item) 'policy-management')}}
|
{{#if (not-eq (policy/typeof item) 'policy-management')}}
|
||||||
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -63,5 +65,4 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</Actions>
|
</Actions>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,14 +1,38 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-policy-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{contains 'Name' @filter.searchproperties}}>Name</Option>
|
||||||
|
<Option @value="Description" @selected={{contains 'Description' @filter.searchproperties}}>Description</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="select-dcs"
|
class="select-dcs"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.dc}}
|
@onchange={{action @onfilter.dc}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -19,16 +43,16 @@
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
{{#each dcs as |dc|}}
|
{{#each dcs as |dc|}}
|
||||||
<Option @value={{dc.Name}} @selected={{contains dc.Name filter.dcs}}>{{dc.Name}}</Option>
|
<Option @value={{@dc.Name}} @selected={{contains dc.Name @filter.dcs}}>{{dc.Name}}</Option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
<DataSource @src="/*/*/datacenters" @loading="lazy" @onchange={{action (mut dcs) value="data"}} />
|
<DataSource @src="/*/*/datacenters" @loading="lazy" @onchange={{action (mut this.dcs) value="data"}} />
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="select-type"
|
class="select-type"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.kind}}
|
@onchange={{action @onfilter.kind}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -38,8 +62,8 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option @value="global-management" @selected={{contains 'global-management' filter.kinds}}>Global Management</Option>
|
<Option @value="global-management" @selected={{contains 'global-management' @filter.kinds}}>Global Management</Option>
|
||||||
<Option @value="standard" @selected={{contains 'standard' filter.kinds}}>Standard</Option>
|
<Option @value="standard" @selected={{contains 'standard' @filter.kinds}}>Standard</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
|
@ -49,7 +73,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -60,15 +84,15 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Name">
|
<Optgroup @label="Name">
|
||||||
<Option @value="Name:asc" @selected={{eq "Name:asc" sort}}>A to Z</Option>
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Name:desc" @selected={{eq "Name:desc" sort}}>Z to A</Option>
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@glimmer/component';
|
||||||
|
|
||||||
export default Component.extend({});
|
export default class ConsulPolicySearchBarComponent extends Component {}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} class="consul-role-list" as |item|>
|
class="consul-role-list"
|
||||||
|
...attributes
|
||||||
|
@items={{@items}}
|
||||||
|
as |item|>
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="header">
|
||||||
<a data-test-role={{item.Name}} href={{href-to 'dc.acls.roles.edit' item.ID}}>{{item.Name}}</a>
|
<a data-test-role={{item.Name}} href={{href-to 'dc.acls.roles.edit' item.ID}}>{{item.Name}}</a>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -19,7 +22,7 @@
|
||||||
Edit
|
Edit
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -41,5 +44,4 @@
|
||||||
</Action>
|
</Action>
|
||||||
</Actions>
|
</Actions>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,15 +1,40 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-role-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{contains 'Name' @filter.searchproperties}}>Name</Option>
|
||||||
|
<Option @value="Description" @selected={{contains 'Description' @filter.searchproperties}}>Description</Option>
|
||||||
|
<Option @value="Policy" @selected={{contains 'Policy' @filter.searchproperties}}>Policy</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="sort">
|
<div class="sort">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -22,19 +47,19 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Name">
|
<Optgroup @label="Name">
|
||||||
<Option @value="Name:asc" @selected={{eq "Name:asc" sort}}>A to Z</Option>
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Name:desc" @selected={{eq "Name:desc" sort}}>Z to A</Option>
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Creation">
|
<Optgroup @label="Creation">
|
||||||
<Option @value="CreateIndex:desc" @selected={{eq "CreateIndex:desc" sort}}>Newest to oldest</Option>
|
<Option @value="CreateIndex:desc" @selected={{eq "CreateIndex:desc" @sort}}>Newest to oldest</Option>
|
||||||
<Option @value="CreateIndex:asc" @selected={{eq "CreateIndex:asc" sort}}>Oldest to newest</Option>
|
<Option @value="CreateIndex:asc" @selected={{eq "CreateIndex:asc" @sort}}>Oldest to newest</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,84 +1,86 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} class="consul-service-instance-list" as |item index|>
|
class="consul-service-instance-list"
|
||||||
<BlockSlot @name="header">
|
...attributes
|
||||||
{{#if (eq routeName "dc.services.show")}}
|
@items={{@items}}
|
||||||
<a data-test-service-name href={{href-to routeName item.Service}}>
|
as |item index|>
|
||||||
{{item.ID}}
|
<BlockSlot @name="header">
|
||||||
</a>
|
{{#if (eq @routeName "dc.services.show")}}
|
||||||
{{else}}
|
<a data-test-service-name href={{href-to @routeName item.Service}}>
|
||||||
<a data-test-service-name href={{href-to routeName item.Service.Service item.Node.Node (or item.Service.ID item.Service.Service)}}>
|
{{item.ID}}
|
||||||
{{item.Service.ID}}
|
</a>
|
||||||
</a>
|
|
||||||
{{/if}}
|
|
||||||
</BlockSlot>
|
|
||||||
<BlockSlot @name="details">
|
|
||||||
{{#if checks}}
|
|
||||||
<Consul::ExternalSource @item={{item}} />
|
|
||||||
<Consul::InstanceChecks @type="service" @items={{get checks item.Service}} />
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<Consul::ExternalSource @item={{item.Service}} />
|
<a data-test-service-name href={{href-to @routeName item.Service.Service item.Node.Node (or item.Service.ID item.Service.Service)}}>
|
||||||
<Consul::InstanceChecks @type="service" @items={{filter-by 'ServiceID' '' item.Checks}} />
|
{{item.Service.ID}}
|
||||||
<Consul::InstanceChecks @type="node" @items={{reject-by 'ServiceID' '' item.Checks}} />
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="details">
|
||||||
|
{{#if @checks}}
|
||||||
|
<Consul::ExternalSource @item={{item}} />
|
||||||
|
<Consul::InstanceChecks @type="service" @items={{get @checks item.Service}} />
|
||||||
|
{{else}}
|
||||||
|
<Consul::ExternalSource @item={{item.Service}} />
|
||||||
|
<Consul::InstanceChecks @type="service" @items={{filter-by 'ServiceID' '' item.Checks}} />
|
||||||
|
<Consul::InstanceChecks @type="node" @items={{reject-by 'ServiceID' '' item.Checks}} />
|
||||||
|
{{/if}}
|
||||||
{{#if item.ProxyInstance}}
|
{{#if item.ProxyInstance}}
|
||||||
<dl class="mesh">
|
<dl class="mesh">
|
||||||
<dt>
|
<dt>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
This service uses a proxy for the Consul service mesh
|
This service uses a proxy for the Consul service mesh
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</dt>
|
</dt>
|
||||||
<dd data-test-mesh>
|
<dd data-test-mesh>
|
||||||
in service mesh with proxy
|
in service mesh with proxy
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (gt item.Node.Node.length 0)}}
|
{{#if (gt item.Node.Node.length 0)}}
|
||||||
<dl class="node">
|
<dl class="node">
|
||||||
<dt>
|
<dt>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
Node
|
Node
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<a href={{href-to 'dc.nodes.show' item.Node.Node}}>{{item.Node.Node}}</a>
|
<a href={{href-to 'dc.nodes.show' item.Node.Node}}>{{item.Node.Node}}</a>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if item.Service.Port}}
|
{{#if item.Service.Port}}
|
||||||
<dl class="address" data-test-address>
|
<dl class="address" data-test-address>
|
||||||
<dt>
|
<dt>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
IP Address and Port
|
IP Address and Port
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{#if (not-eq item.Service.Address '')}}
|
{{#if (not-eq item.Service.Address '')}}
|
||||||
{{item.Service.Address}}:{{item.Service.Port}}
|
{{item.Service.Address}}:{{item.Service.Port}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{item.Node.Address}}:{{item.Service.Port}}
|
{{item.Node.Address}}:{{item.Service.Port}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (and checks item.Port)}}
|
{{#if (and @checks item.Port)}}
|
||||||
<dl class="port">
|
<dl class="port">
|
||||||
<dt>
|
<dt>
|
||||||
Port
|
Port
|
||||||
</dt>
|
</dt>
|
||||||
<dd data-test-service-port={{item.Port}}>
|
<dd data-test-service-port={{item.Port}}>
|
||||||
<CopyButton
|
<CopyButton
|
||||||
@value={{item.Port}}
|
@value={{item.Port}}
|
||||||
@name="Port"
|
@name="Port"
|
||||||
/>
|
/>
|
||||||
:{{item.Port}}
|
:{{item.Port}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if checks}}
|
{{#if checks}}
|
||||||
<TagList @item={{item}} />
|
<TagList @item={{item}} />
|
||||||
{{else}}
|
{{else}}
|
||||||
<TagList @item={{item.Service}} />
|
<TagList @item={{item.Service}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,14 +1,43 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-service-instance-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{contains 'Name' @filter.searchproperties}}>Name</Option>
|
||||||
|
<Option @value="Tags" @selected={{contains 'Tags' @filter.searchproperties}}>Tags</Option>
|
||||||
|
<Option @value="ID" @selected={{contains 'ID' @filter.searchproperties}}>Service ID</Option>
|
||||||
|
<Option @value="Address" @selected={{contains 'Address' @filter.searchproperties}}>Address</Option>
|
||||||
|
<Option @value="Port" @selected={{contains 'Port' @filter.searchproperties}}>Port</Option>
|
||||||
|
<Option @value="Service.Meta" @selected={{contains 'Service.Meta' @filter.searchproperties}}>Service Meta</Option>
|
||||||
|
<Option @value="Node.Meta" @selected={{contains 'Node.Meta' @filter.searchproperties}}>Node Meta</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-status"
|
class="type-status"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.status}}
|
@onchange={{action @onfilter.status}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -18,18 +47,18 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option class="value-passing" @value="passing" @selected={{contains 'passing' filter.statuses}}>Passing</Option>
|
<Option class="value-passing" @value="passing" @selected={{contains 'passing' @filter.statuses}}>Passing</Option>
|
||||||
<Option class="value-warning" @value="warning" @selected={{contains 'warning' filter.statuses}}>Warning</Option>
|
<Option class="value-warning" @value="warning" @selected={{contains 'warning' @filter.statuses}}>Warning</Option>
|
||||||
<Option class="value-critical" @value="critical" @selected={{contains 'critical' filter.statuses}}>Failing</Option>
|
<Option class="value-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' filter.statuses}}>No checks</Option>
|
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
{{#if (gt sources.length 0)}}
|
{{#if (gt @sources.length 0)}}
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-source"
|
class="type-source"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.source}}
|
@onchange={{action @onfilter.source}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -39,8 +68,8 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
{{#each sources as |source|}}
|
{{#each @sources as |source|}}
|
||||||
<Option class={{source}} @value={{source}} @selected={{contains source filter.sources}}>{{source}}</Option>
|
<Option class={{source}} @value={{source}} @selected={{contains source @filter.sources}}>{{source}}</Option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -52,7 +81,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -65,19 +94,19 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Health Status">
|
<Optgroup @label="Health Status">
|
||||||
<Option @value="Status:asc" @selected={{eq "Status:asc" sort}}>Unhealthy to Healthy</Option>
|
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort}}>Unhealthy to Healthy</Option>
|
||||||
<Option @value="Status:desc" @selected={{eq "Status:desc" sort}}>Healthy to Unhealthy</Option>
|
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort}}>Healthy to Unhealthy</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Service Name">
|
<Optgroup @label="Service Name">
|
||||||
<Option @value="Name:asc" @selected={{eq "Name:asc" sort}}>A to Z</Option>
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Name:desc" @selected={{eq "Name:desc" sort}}>Z to A</Option>
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,5 +1,10 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} @linkable={{action "isLinkable"}} class="consul-service-list" as |item index|>
|
class="consul-service-list"
|
||||||
|
...attributes
|
||||||
|
@items={{@items}}
|
||||||
|
@linkable={{action this.isLinkable}}
|
||||||
|
as |item index|
|
||||||
|
>
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="header">
|
||||||
<dl class={{item.MeshStatus}}>
|
<dl class={{item.MeshStatus}}>
|
||||||
<dt>
|
<dt>
|
||||||
|
@ -84,5 +89,4 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<TagList @item={{item}} />
|
<TagList @item={{item}} />
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
|
|
@ -1,11 +1,9 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@glimmer/component';
|
||||||
import { get } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
|
|
||||||
export default Component.extend({
|
export default class ConsulServiceList extends Component {
|
||||||
tagName: '',
|
@action
|
||||||
actions: {
|
isLinkable(item) {
|
||||||
isLinkable: function(item) {
|
return item.InstanceCount > 0;
|
||||||
return get(item, 'InstanceCount') > 0;
|
}
|
||||||
},
|
}
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,14 +1,38 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-service-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{contains 'Name' @filter.searchproperties}}>Name</Option>
|
||||||
|
<Option @value="Tags" @selected={{contains 'Tags' @filter.searchproperties}}>Tags</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-status"
|
class="type-status"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.status}}
|
@onchange={{action @onfilter.status}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -18,16 +42,16 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option class="value-passing" @value="passing" @selected={{contains 'passing' filter.statuses}}>Passing</Option>
|
<Option class="value-passing" @value="passing" @selected={{contains 'passing' @filter.statuses}}>Passing</Option>
|
||||||
<Option class="value-warning" @value="warning" @selected={{contains 'warning' filter.statuses}}>Warning</Option>
|
<Option class="value-warning" @value="warning" @selected={{contains 'warning' @filter.statuses}}>Warning</Option>
|
||||||
<Option class="value-critical" @value="critical" @selected={{contains 'critical' filter.statuses}}>Failing</Option>
|
<Option class="value-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' filter.statuses}}>No checks</Option>
|
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.kind}}
|
@onchange={{action @onfilter.kind}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -37,24 +61,24 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option @value="service" @selected={{contains 'service' filter.kinds}}>Service</Option>
|
<Option @value="service" @selected={{contains 'service' @filter.kinds}}>Service</Option>
|
||||||
<Optgroup @label="Gateway">
|
<Optgroup @label="Gateway">
|
||||||
<Option @value="ingress-gateway" @selected={{contains 'ingress-gateway' filter.kinds}}>Ingress Gateway</Option>
|
<Option @value="ingress-gateway" @selected={{contains 'ingress-gateway' @filter.kinds}}>Ingress Gateway</Option>
|
||||||
<Option @value="terminating-gateway" @selected={{contains 'terminating-gateway' filter.kinds}}>Terminating Gateway</Option>
|
<Option @value="terminating-gateway" @selected={{contains 'terminating-gateway' @filter.kinds}}>Terminating Gateway</Option>
|
||||||
<Option @value="mesh-gateway" @selected={{contains 'mesh-gateway' filter.kinds}}>Mesh Gateway</Option>
|
<Option @value="mesh-gateway" @selected={{contains 'mesh-gateway' @filter.kinds}}>Mesh Gateway</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Mesh">
|
<Optgroup @label="Mesh">
|
||||||
<Option @value="in-mesh" @selected={{contains 'in-mesh' filter.kinds}}>In service mesh</Option>
|
<Option @value="in-mesh" @selected={{contains 'in-mesh' @filter.kinds}}>In service mesh</Option>
|
||||||
<Option @value="not-in-mesh" @selected={{contains 'not-in-mesh' filter.kinds}}>Not in service mesh</Option>
|
<Option @value="not-in-mesh" @selected={{contains 'not-in-mesh' @filter.kinds}}>Not in service mesh</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
{{#if (gt sources.length 0)}}
|
{{#if (gt @sources.length 0)}}
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
class="type-source"
|
class="type-source"
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.source}}
|
@onchange={{action @onfilter.source}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -64,8 +88,8 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
{{#each sources as |source|}}
|
{{#each @sources as |source|}}
|
||||||
<Option class={{source}} @value={{source}} @selected={{contains source filter.sources}}>{{source}}</Option>
|
<Option class={{source}} @value={{source}} @selected={{contains source @filter.sources}}>{{source}}</Option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -77,7 +101,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -90,19 +114,19 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Health Status">
|
<Optgroup @label="Health Status">
|
||||||
<Option @value="Status:asc" @selected={{eq "Status:asc" sort}}>Unhealthy to Healthy</Option>
|
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort}}>Unhealthy to Healthy</Option>
|
||||||
<Option @value="Status:desc" @selected={{eq "Status:desc" sort}}>Healthy to Unhealthy</Option>
|
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort}}>Healthy to Unhealthy</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Service Name">
|
<Optgroup @label="Service Name">
|
||||||
<Option @value="Name:asc" @selected={{eq "Name:asc" sort}}>A to Z</Option>
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Name:desc" @selected={{eq "Name:desc" sort}}>Z to A</Option>
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,7 +1,9 @@
|
||||||
{{#if (gt items.length 0)}}
|
<ListCollection
|
||||||
<ListCollection @items={{items}} class="consul-token-list" as |item|>
|
class="consul-token-list"
|
||||||
|
@items={{@items}}
|
||||||
|
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 @position="top-start">
|
<Tooltip @position="top-start">
|
||||||
|
@ -35,14 +37,14 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{#if (not (token/is-legacy item))}}
|
{{#if (not (token/is-legacy item))}}
|
||||||
<Action data-test-clone-action @onclick={{action onclone item}}>
|
<Action data-test-clone-action @onclick={{action @onclone item}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Duplicate
|
Duplicate
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq item.AccessorID token.AccessorID)}}
|
{{#if (eq item.AccessorID token.AccessorID)}}
|
||||||
<Action data-test-logout-action class="dangerous" @onclick={{action onlogout item}}>
|
<Action data-test-logout-action class="dangerous" @onclick={{action @onlogout item}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Logout
|
Logout
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -63,7 +65,7 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{else}}
|
{{else}}
|
||||||
<Action data-test-use-action @onclick={{action onuse item}}>
|
<Action data-test-use-action @onclick={{action @onuse item}}>
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Use
|
Use
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -84,8 +86,8 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</Action>
|
</Action>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (not (or (token/is-anonymous item) (eq item.AccessorID token.AccessorID)))}}
|
{{#if (not (or (token/is-anonymous item) (eq item.AccessorID @token.AccessorID)))}}
|
||||||
<Action data-test-delete-action @onclick={{action ondelete item}} class="dangerous">
|
<Action data-test-delete-action @onclick={{action @ondelete item}} class="dangerous">
|
||||||
<BlockSlot @name="label">
|
<BlockSlot @name="label">
|
||||||
Delete
|
Delete
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -108,5 +110,4 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</Actions>
|
</Actions>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
{{/if}}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -1,13 +1,39 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-token-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="AccessorID" @selected={{contains 'AccessorID' @filter.searchproperties}}>AccessorID</Option>
|
||||||
|
<Option @value="Description" @selected={{contains 'Description' @filter.searchproperties}}>Description</Option>
|
||||||
|
<Option @value="Policy" @selected={{contains 'Policy' @filter.searchproperties}}>Policy</Option>
|
||||||
|
<Option @value="Role" @selected={{contains 'Role' @filter.searchproperties}}>Role</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.kind}}
|
@onchange={{action @onfilter.kind}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -17,9 +43,9 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option @value="global-management" @selected={{contains 'global-management' filter.kinds}}>Global Management</Option>
|
<Option @value="global-management" @selected={{contains 'global-management' @filter.kinds}}>Global Management</Option>
|
||||||
<Option @value="global" @selected={{contains 'global' filter.kinds}}>Global</Option>
|
<Option @value="global" @selected={{contains 'global' @filter.kinds}}>Global Scope</Option>
|
||||||
<Option @value="local" @selected={{contains 'local' filter.kinds}}>Local</Option>
|
<Option @value="local" @selected={{contains 'local' @filter.kinds}}>Local Scope</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
|
@ -29,7 +55,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -40,15 +66,15 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Creation">
|
<Optgroup @label="Creation">
|
||||||
<Option @value="CreateTime:desc" @selected={{eq "CreateTime:desc" sort}}>Newest to oldest</Option>
|
<Option @value="CreateTime:desc" @selected={{eq "CreateTime:desc" @sort}}>Newest to oldest</Option>
|
||||||
<Option @value="CreateTime:asc" @selected={{eq "CreateTime:asc" sort}}>Oldest to newest</Option>
|
<Option @value="CreateTime:asc" @selected={{eq "CreateTime:asc" @sort}}>Oldest to newest</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({});
|
|
|
@ -1,4 +1,9 @@
|
||||||
<ListCollection @items={{items}} @linkable={{action "isLinkable"}} class="consul-upstream-list" as |item index|>
|
<ListCollection
|
||||||
|
class="consul-upstream-list"
|
||||||
|
...attributes
|
||||||
|
@items={{@items}}
|
||||||
|
@linkable={{action this.isLinkable}}
|
||||||
|
as |item index|>
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="header">
|
||||||
{{#if (gt item.InstanceCount 0)}}
|
{{#if (gt item.InstanceCount 0)}}
|
||||||
<dl class={{item.MeshStatus}}>
|
<dl class={{item.MeshStatus}}>
|
||||||
|
@ -19,8 +24,9 @@
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{#if (and (env 'CONSUL_NSPACES_ENABLED') (not-eq item.Namespace nspace))}}
|
{{#if (and (env 'CONSUL_NSPACES_ENABLED') (not-eq item.Namespace @nspace))}}
|
||||||
<a data-test-service-name href={{href-to 'nspace.dc.services.show' (concat '~' item.Namespace) dc item.Name }}>
|
{{item.Namespace}}
|
||||||
|
<a data-test-service-name href={{href-to 'nspace.dc.services.show' (concat '~' item.Namespace) @dc item.Name }}>
|
||||||
{{item.Name}}
|
{{item.Name}}
|
||||||
</a>
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -35,11 +41,11 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="details">
|
<BlockSlot @name="details">
|
||||||
{{#if (and (env 'CONSUL_NSPACES_ENABLED') (not-eq item.Namespace nspace))}}
|
{{#if (and (env 'CONSUL_NSPACES_ENABLED') (not-eq item.Namespace @nspace))}}
|
||||||
<dl class="nspace">
|
<dl class="nspace">
|
||||||
<dt>
|
<dt>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
Namespace
|
Namespace
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
@ -47,18 +53,19 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (gt item.GatewayConfig.Addresses.length 0)}}
|
|
||||||
{{#each item.GatewayConfig.Addresses as |address|}}
|
{{#each item.GatewayConfig.Addresses as |address|}}
|
||||||
<dl>
|
<dl>
|
||||||
<dt>
|
<dt>
|
||||||
|
<span>Address</span>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
<CopyButton
|
<CopyButton
|
||||||
@value={{address}}
|
@value={{address}}
|
||||||
@name="Address"
|
@name="Address"
|
||||||
/>
|
/>
|
||||||
</dt>
|
{{address}}
|
||||||
<dd>{{address}}</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ListCollection>
|
</ListCollection>
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@glimmer/component';
|
||||||
import { get } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
|
|
||||||
export default Component.extend({
|
export default class ConsulServiceList extends Component {
|
||||||
tagName: '',
|
@action
|
||||||
actions: {
|
isLinkable(item) {
|
||||||
isLinkable: function(item) {
|
return item.InstanceCount > 0;
|
||||||
return get(item, 'InstanceCount') > 0;
|
}
|
||||||
},
|
}
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,13 +1,37 @@
|
||||||
<form class="filter-bar">
|
<form
|
||||||
<FreetextFilter
|
class="consul-upstream-search-bar filter-bar"
|
||||||
@onsearch={{action onsearch}}
|
...attributes
|
||||||
@value={{search}}
|
>
|
||||||
@placeholder="Search"
|
<div class="search">
|
||||||
/>
|
<FreetextFilter
|
||||||
|
@onsearch={{action @onsearch}}
|
||||||
|
@value={{@search}}
|
||||||
|
@placeholder="Search"
|
||||||
|
>
|
||||||
|
<PopoverSelect
|
||||||
|
class="type-search-properties"
|
||||||
|
@position="right"
|
||||||
|
@onchange={{action @onfilter.searchproperty}}
|
||||||
|
@multiple={{true}}
|
||||||
|
as |components|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{contains 'Name' @filter.searchproperties}}>Name</Option>
|
||||||
|
<Option @value="Tags" @selected={{contains 'Tags' @filter.searchproperties}}>Tags</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>
|
||||||
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<PopoverSelect
|
<PopoverSelect
|
||||||
@position="left"
|
@position="left"
|
||||||
@onchange={{action onfilter.instance}}
|
@onchange={{action @onfilter.instance}}
|
||||||
@multiple={{true}}
|
@multiple={{true}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -17,8 +41,8 @@
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Option @value="registered" @selected={{contains 'registered' filter.instances}}>Registered</Option>
|
<Option @value="registered" @selected={{contains 'registered' @filter.instances}}>Registered</Option>
|
||||||
<Option @value="not-registered" @selected={{contains 'not-registered' filter.instances}}>Not Registered</Option>
|
<Option @value="not-registered" @selected={{contains 'not-registered' @filter.instances}}>Not Registered</Option>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</PopoverSelect>
|
</PopoverSelect>
|
||||||
|
@ -28,7 +52,7 @@
|
||||||
class="type-sort"
|
class="type-sort"
|
||||||
data-test-sort-control
|
data-test-sort-control
|
||||||
@position="right"
|
@position="right"
|
||||||
@onchange={{action onsort}}
|
@onchange={{action @onsort}}
|
||||||
@multiple={{false}}
|
@multiple={{false}}
|
||||||
as |components|>
|
as |components|>
|
||||||
<BlockSlot @name="selected">
|
<BlockSlot @name="selected">
|
||||||
|
@ -41,19 +65,19 @@
|
||||||
))
|
))
|
||||||
as |selectable|
|
as |selectable|
|
||||||
}}
|
}}
|
||||||
{{get selectable sort}}
|
{{get selectable @sort}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</span>
|
</span>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="options">
|
<BlockSlot @name="options">
|
||||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||||
<Optgroup @label="Health Status">
|
<Optgroup @label="Health Status">
|
||||||
<Option @value="Status:asc" @selected={{eq "Status:asc" sort}}>Unhealthy to Healthy</Option>
|
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort}}>Unhealthy to Healthy</Option>
|
||||||
<Option @value="Status:desc" @selected={{eq "Status:desc" sort}}>Healthy to Unhealthy</Option>
|
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort}}>Healthy to Unhealthy</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
<Optgroup @label="Service Name">
|
<Optgroup @label="Service Name">
|
||||||
<Option @value="Name:asc" @selected={{eq "Name:asc" sort}}>A to Z</Option>
|
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort}}>A to Z</Option>
|
||||||
<Option @value="Name:desc" @selected={{eq "Name:desc" sort}}>Z to A</Option>
|
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort}}>Z to A</Option>
|
||||||
</Optgroup>
|
</Optgroup>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
tagName: '',
|
|
||||||
});
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{{yield (hash
|
||||||
|
items=this.items
|
||||||
|
Collection=(if (gt this.items.length 0) (component 'anonymous') '')
|
||||||
|
Empty=(if (eq this.items.length 0) (component 'anonymous') '')
|
||||||
|
)}}
|
|
@ -0,0 +1,56 @@
|
||||||
|
import Component from '@glimmer/component';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { sort } from '@ember/object/computed';
|
||||||
|
import { defineProperty } from '@ember/object';
|
||||||
|
|
||||||
|
export default class DataCollectionComponent extends Component {
|
||||||
|
@service('filter') filter;
|
||||||
|
@service('sort') sort;
|
||||||
|
@service('search') search;
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return this.args.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
get items() {
|
||||||
|
// the ember sort computed accepts either:
|
||||||
|
// 1. The name of a property (as a string) returning an array properties to sort by
|
||||||
|
// 2. A function to use for sorting
|
||||||
|
let comparator = 'comparator';
|
||||||
|
if (typeof this.comparator === 'function') {
|
||||||
|
comparator = this.comparator;
|
||||||
|
}
|
||||||
|
defineProperty(this, 'sorted', sort('searched', comparator));
|
||||||
|
return this.sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
get searched() {
|
||||||
|
if (typeof this.args.search === 'undefined') {
|
||||||
|
return this.filtered;
|
||||||
|
}
|
||||||
|
const predicate = this.search.predicate(this.type);
|
||||||
|
const options = {};
|
||||||
|
if (typeof this.args.filters.searchproperties !== 'undefined') {
|
||||||
|
options.properties = this.args.filters.searchproperties;
|
||||||
|
}
|
||||||
|
return this.filtered.filter(predicate(this.args.search, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
get filtered() {
|
||||||
|
if (typeof this.args.filters === 'undefined') {
|
||||||
|
return this.args.items;
|
||||||
|
}
|
||||||
|
const predicate = this.filter.predicate(this.type);
|
||||||
|
if (typeof predicate === 'undefined') {
|
||||||
|
return this.args.items;
|
||||||
|
}
|
||||||
|
return this.args.items.filter(predicate(this.args.filters));
|
||||||
|
}
|
||||||
|
|
||||||
|
get comparator() {
|
||||||
|
if (typeof this.args.sort === 'undefined') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return this.sort.comparator(this.type)(this.args.sort);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
@import './skin';
|
||||||
|
@import './layout';
|
||||||
|
%filter-bar-reversed {
|
||||||
|
color: inherit;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
.filter-bar {
|
||||||
|
&,
|
||||||
|
> div {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
& {
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
.sort {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.popover-select {
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.popover-menu > [type='checkbox'] + label button {
|
||||||
|
padding-left: 1.5rem !important;
|
||||||
|
padding-right: 1.5rem !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
.popover-menu [role='menuitem'] {
|
||||||
|
justify-content: normal !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media #{$--lt-horizontal-filters} {
|
||||||
|
.filter-bar {
|
||||||
|
&,
|
||||||
|
& > div {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
position: relative;
|
||||||
|
z-index: 4;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: .3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media #{$--lt-horizontal-selects} {
|
||||||
|
.filter-bar {
|
||||||
|
.filters, .sort {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
.filter-bar {
|
||||||
|
& {
|
||||||
|
background-color: $gray-010;
|
||||||
|
border-bottom: $decor-border-100;
|
||||||
|
border-color: $gray-200;
|
||||||
|
}
|
||||||
|
.filters, .sort {
|
||||||
|
.popover-menu > [type='checkbox']:checked + label button {
|
||||||
|
color: $blue-500;
|
||||||
|
background-color: $gray-100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
|
||||||
|
import { hbs } from 'ember-cli-htmlbars';
|
||||||
|
|
||||||
|
<Meta title="Components/FreetextFilter" />
|
||||||
|
|
||||||
|
# FreetextFilter
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story
|
||||||
|
name="Basic"
|
||||||
|
argTypes={{
|
||||||
|
}}
|
||||||
|
>{(args) => ({
|
||||||
|
template: hbs`<FreetextFilter />`,
|
||||||
|
context: args
|
||||||
|
})}
|
||||||
|
</Story>
|
||||||
|
<Story
|
||||||
|
name="Search Across"
|
||||||
|
argTypes={{
|
||||||
|
}}
|
||||||
|
>{(args) => ({
|
||||||
|
template: hbs`<FreetextFilter>
|
||||||
|
<PopoverSelect
|
||||||
|
@position="right"
|
||||||
|
@multiple={{true}}
|
||||||
|
as |popover|>
|
||||||
|
<BlockSlot @name="selected">
|
||||||
|
<span>
|
||||||
|
Search across
|
||||||
|
</span>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="options">
|
||||||
|
{{#let popover.Optgroup popover.Option as |Optgroup Option|}}
|
||||||
|
<Option @value="Name" @selected={{true}}>Name</Option>
|
||||||
|
<Option @value="Tags">Tags</Option>
|
||||||
|
{{/let}}
|
||||||
|
</BlockSlot>
|
||||||
|
</PopoverSelect>
|
||||||
|
</FreetextFilter>`,
|
||||||
|
context: args
|
||||||
|
})}
|
||||||
|
</Story>
|
||||||
|
</Canvas>
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
<fieldset class="freetext-filter">
|
<fieldset
|
||||||
<label class="type-search">
|
class="freetext-filter"
|
||||||
<span>Search</span>
|
...attributes
|
||||||
<input type="search" onsearch={{action "change"}} oninput={{action "change"}} onkeydown={{action "keydown"}} name="s" value={{value}} placeholder={{placeholder}} autofocus="autofocus" />
|
>
|
||||||
</label>
|
<label class="type-search">
|
||||||
|
<span class="freetext-filter_label">Search</span>
|
||||||
|
<input
|
||||||
|
class="freetext-filter_input"
|
||||||
|
type="search"
|
||||||
|
onsearch={{action this.change}}
|
||||||
|
oninput={{action this.change}}
|
||||||
|
onkeydown={{action this.keydown}}
|
||||||
|
name="s" value={{@value}}
|
||||||
|
placeholder={{this.placeholder}}
|
||||||
|
autofocus="autofocus"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
{{yield}}
|
||||||
</fieldset>
|
</fieldset>
|
|
@ -1,19 +1,25 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@glimmer/component';
|
||||||
import { inject as service } from '@ember/service';
|
import { action } from '@ember/object';
|
||||||
|
|
||||||
const ENTER = 13;
|
const ENTER = 13;
|
||||||
export default Component.extend({
|
export default class FreetextFilter extends Component {
|
||||||
dom: service('dom'),
|
get placeholder() {
|
||||||
tagName: '',
|
return this.args.placeholder || 'Search';
|
||||||
actions: {
|
}
|
||||||
change: function(e) {
|
|
||||||
this.onsearch(
|
get onsearch() {
|
||||||
this.dom.setEventTargetProperty(e, 'value', value => (value === '' ? undefined : value))
|
return this.args.onsearch || (() => {});
|
||||||
);
|
}
|
||||||
},
|
|
||||||
keydown: function(e) {
|
@action
|
||||||
if (e.keyCode === ENTER) {
|
change(e) {
|
||||||
e.preventDefault();
|
this.onsearch(e);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
@action
|
||||||
});
|
keydown(e) {
|
||||||
|
if (e.keyCode === ENTER) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
.freetext-filter {
|
||||||
|
--height: 2.2rem;
|
||||||
|
& {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
height: var(--height);
|
||||||
|
}
|
||||||
|
&_input,
|
||||||
|
& > label {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
&_input,
|
||||||
|
&_label {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
&_input {
|
||||||
|
padding: 8px 10px;
|
||||||
|
padding-left: var(--height);
|
||||||
|
min-width: 12.7rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
&_label {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
width: var(--height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
.freetext-filter {
|
||||||
|
& {
|
||||||
|
border: $decor-border-100;
|
||||||
|
border-radius: $decor-radius-100;
|
||||||
|
|
||||||
|
background-color: $white;
|
||||||
|
border-color: $gray-200;
|
||||||
|
color: $gray-400;
|
||||||
|
}
|
||||||
|
&:hover,
|
||||||
|
&:hover * {
|
||||||
|
border-color: $gray-400;
|
||||||
|
}
|
||||||
|
& *,
|
||||||
|
&_input::placeholder {
|
||||||
|
cursor: inherit;
|
||||||
|
color: inherit;
|
||||||
|
border-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_input {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
&_label::after {
|
||||||
|
@extend %as-pseudo;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-left: -8px;
|
||||||
|
margin-top: -8px;
|
||||||
|
}
|
||||||
|
&_label::after {
|
||||||
|
@extend %with-search-mask;
|
||||||
|
}
|
||||||
|
.popover-menu {
|
||||||
|
background-color: $gray-050;
|
||||||
|
color: $gray-800;
|
||||||
|
}
|
||||||
|
.popover-menu {
|
||||||
|
border-left: 1px solid;
|
||||||
|
border-color: inherit;
|
||||||
|
}
|
||||||
|
.popover-menu > [type='checkbox']:checked + label button {
|
||||||
|
background-color: $gray-200;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,12 @@
|
||||||
<div class="more-popover-menu">
|
<div
|
||||||
<PopoverMenu @expanded={{expanded}} @onchange={{action onchange}} @keyboardAccess={{false}} as |components api|>
|
class="more-popover-menu"
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<PopoverMenu
|
||||||
|
@expanded={{expanded}}
|
||||||
|
@onchange={{action onchange}}
|
||||||
|
@keyboardAccess={{false}}
|
||||||
|
as |components api|>
|
||||||
<BlockSlot @name="trigger">
|
<BlockSlot @name="trigger">
|
||||||
More
|
More
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
{{yield}}
|
{{yield}}
|
||||||
<div class="popover-menu" ...attributes>
|
<div
|
||||||
<AriaMenu @keyboardAccess={{keyboardAccess}} as |change keypress keypressClick aria|>
|
class="popover-menu"
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<AriaMenu @keyboardAccess={{keyboardAccess}} as |change keypress keypressClick aria|>
|
||||||
|
|
||||||
{{#let (hash
|
{{#let (hash
|
||||||
MenuItem=(component
|
MenuItem=(component
|
||||||
|
@ -18,46 +21,46 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
as |components|}}
|
as |components|}}
|
||||||
{{#let (hash
|
{{#let (hash
|
||||||
toggle=this.toggle.click
|
toggle=this.toggle.click
|
||||||
)
|
)
|
||||||
as |api|}}
|
as |api|}}
|
||||||
|
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
@checked={{if keyboardAccess aria.expanded expanded}}
|
@checked={{if keyboardAccess aria.expanded expanded}}
|
||||||
@onchange={{queue change (action "change")}}
|
@onchange={{queue change (action "change")}}
|
||||||
as |toggle|>
|
as |toggle|>
|
||||||
<Ref @target={{this}} @name="toggle" @value={{toggle}} />
|
<Ref @target={{this}} @name="toggle" @value={{toggle}} />
|
||||||
<button type="button" aria-haspopup="menu" onkeydown={{keypress}} onclick={{this.toggle.click}} id={{aria.labelledBy}} aria-controls={{aria.controls}}>
|
<button type="button" aria-haspopup="menu" onkeydown={{keypress}} onclick={{this.toggle.click}} id={{aria.labelledBy}} aria-controls={{aria.controls}}>
|
||||||
<YieldSlot @name="trigger">
|
<YieldSlot @name="trigger">
|
||||||
{{yield components api}}
|
{{yield components api}}
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
</button>
|
</button>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
|
|
||||||
<MenuPanel @position={{position}} id={{aria.controls}} aria-labelledby={{aria.labelledBy}} aria-expanded={{aria.expanded}} as |menu|>
|
<MenuPanel @position={{position}} id={{aria.controls}} aria-labelledby={{aria.labelledBy}} aria-expanded={{aria.expanded}} as |menu|>
|
||||||
<Ref @target={{this}} @name="menu" @value={{menu}} />
|
<Ref @target={{this}} @name="menu" @value={{menu}} />
|
||||||
<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}} onchange={{menu.change}} />
|
<input type="checkbox" id={{concat 'popover-menu-' guid '-' sub}} onchange={{menu.change}} />
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
</BlockSlot>
|
||||||
|
{{#if hasHeader}}
|
||||||
|
<BlockSlot @name="header">
|
||||||
|
{{yield components api}}
|
||||||
|
{{#yield-slot name="header"}}{{else}}{{/yield-slot}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
{{#if hasHeader}}
|
{{/if}}
|
||||||
<BlockSlot @name="header">
|
<BlockSlot @name="menu">
|
||||||
{{yield components api}}
|
<YieldSlot @name="menu" @params={{block-params (concat "popover-menu-" guid "-") send keypressClick this.toggle.click}}>
|
||||||
{{#yield-slot name="header"}}{{else}}{{/yield-slot}}
|
{{yield components api}}
|
||||||
</BlockSlot>
|
</YieldSlot>
|
||||||
{{/if}}
|
</BlockSlot>
|
||||||
<BlockSlot @name="menu">
|
</MenuPanel>
|
||||||
<YieldSlot @name="menu" @params={{block-params (concat "popover-menu-" guid "-") send keypressClick this.toggle.click}}>
|
|
||||||
{{yield components api}}
|
|
||||||
</YieldSlot>
|
|
||||||
</BlockSlot>
|
|
||||||
</MenuPanel>
|
|
||||||
|
|
||||||
{{/let}}
|
{{/let}}
|
||||||
{{/let}}
|
{{/let}}
|
||||||
|
|
||||||
</AriaMenu>
|
</AriaMenu>
|
||||||
</div>
|
</div>
|
|
@ -7,7 +7,7 @@
|
||||||
<div role="menu">
|
<div role="menu">
|
||||||
<YieldSlot @name="confirmation" @params={{
|
<YieldSlot @name="confirmation" @params={{
|
||||||
block-params (component 'confirmation-alert'
|
block-params (component 'confirmation-alert'
|
||||||
onclick=(queue (action onclick) (action menu.clickTrigger))
|
onclick=(queue (action menu.clickTrigger) (action onclick))
|
||||||
name=(concat menu.confirm guid)
|
name=(concat menu.confirm guid)
|
||||||
)
|
)
|
||||||
}}>{{yield}}</YieldSlot>
|
}}>{{yield}}</YieldSlot>
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
<PopoverMenu @position={{or position "left"}} class="popover-select" ...attributes as |components menu|>
|
<PopoverMenu
|
||||||
|
class="popover-select"
|
||||||
|
...attributes
|
||||||
|
@position={{or position "left"}}
|
||||||
|
as |components menu|
|
||||||
|
>
|
||||||
{{yield}}
|
{{yield}}
|
||||||
{{#let
|
{{#let
|
||||||
(component 'popover-select/optgroup' components=components)
|
(component 'popover-select/optgroup' components=components)
|
||||||
|
@ -28,4 +33,4 @@
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
</PopoverMenu>
|
</PopoverMenu>
|
||||||
|
|
|
@ -40,10 +40,7 @@ export default Component.extend(Slotted, {
|
||||||
this.dom.setEventTargetProperties(e, {
|
this.dom.setEventTargetProperties(e, {
|
||||||
selected: target => value,
|
selected: target => value,
|
||||||
selectedItems: target => {
|
selectedItems: target => {
|
||||||
const opts = [...options];
|
return [...options].join(',');
|
||||||
if (opts.length > 0) {
|
|
||||||
return opts.join(',');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
<input
|
<input
|
||||||
...attributes
|
...attributes
|
||||||
{{ref this "input"}}
|
{{did-insert (set this 'input')}}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={{if checked 'checked' undefined}}
|
checked={{if checked 'checked' undefined}}
|
||||||
id={{concat 'toggle-button-' guid}}
|
id={{concat 'toggle-button-' guid}}
|
||||||
onchange={{action 'change'}}
|
onchange={{action 'change'}}
|
||||||
/>
|
/>
|
||||||
<label {{ref this "label"}} for={{concat 'toggle-button-' guid}}>
|
<label
|
||||||
|
{{did-insert (set this 'label')}}
|
||||||
|
for={{concat 'toggle-button-' guid}}
|
||||||
|
>
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
click=(action 'click')
|
click=(action 'click')
|
||||||
)}}
|
)}}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { action } from '@ember/object';
|
|
||||||
import Controller from '@ember/controller';
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
filterBy: {
|
|
||||||
as: 'type',
|
|
||||||
},
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@action
|
|
||||||
sendClone(item) {
|
|
||||||
this.send('clone', item);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
dc: 'dc',
|
|
||||||
kind: 'kind',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
kind: 'kind',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
access: 'access',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
status: 'status',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -2,17 +2,6 @@ import { computed } from '@ember/object';
|
||||||
import Controller from '@ember/controller';
|
import Controller from '@ember/controller';
|
||||||
|
|
||||||
export default class IndexController extends Controller {
|
export default class IndexController extends Controller {
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
status: 'status',
|
|
||||||
source: 'source',
|
|
||||||
kind: 'kind',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@computed('items.[]')
|
@computed('items.[]')
|
||||||
get services() {
|
get services() {
|
||||||
return this.items.filter(function(item) {
|
return this.items.filter(function(item) {
|
||||||
|
|
|
@ -2,16 +2,6 @@ import { computed } from '@ember/object';
|
||||||
import Controller from '@ember/controller';
|
import Controller from '@ember/controller';
|
||||||
|
|
||||||
export default class InstancesController extends Controller {
|
export default class InstancesController extends Controller {
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
status: 'status',
|
|
||||||
source: 'source',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
@computed('items')
|
@computed('items')
|
||||||
get externalSources() {
|
get externalSources() {
|
||||||
const sources = this.items.reduce(function(prev, item) {
|
const sources = this.items.reduce(function(prev, item) {
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
export default class IndexController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
access: 'access',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class ServicesController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
instance: 'instance',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import Controller from '@ember/controller';
|
|
||||||
|
|
||||||
export default class UpstreamsController extends Controller {
|
|
||||||
queryParams = {
|
|
||||||
sortBy: 'sort',
|
|
||||||
instance: 'instance',
|
|
||||||
search: {
|
|
||||||
as: 'filter',
|
|
||||||
replace: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export default {
|
||||||
|
kinds: {
|
||||||
|
management: (item, value) => item.Type === value,
|
||||||
|
client: (item, value) => item.Type === value,
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,9 +1,7 @@
|
||||||
import { andOr } from 'consul-ui/utils/filter';
|
export default {
|
||||||
|
|
||||||
export default andOr({
|
|
||||||
accesses: {
|
accesses: {
|
||||||
allow: (item, value) => item.Action === value,
|
allow: (item, value) => item.Action === value,
|
||||||
deny: (item, value) => item.Action === value,
|
deny: (item, value) => item.Action === value,
|
||||||
'app-aware': (item, value) => typeof item.Action === 'undefined',
|
'app-aware': (item, value) => typeof item.Action === 'undefined',
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
export default {
|
||||||
|
kinds: {
|
||||||
|
folder: (item, value) => item.isFolder,
|
||||||
|
key: (item, value) => !item.isFolder,
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,10 +1,7 @@
|
||||||
import setHelpers from 'mnemonist/set';
|
export default {
|
||||||
import { andOr } from 'consul-ui/utils/filter';
|
|
||||||
|
|
||||||
export default andOr({
|
|
||||||
statuses: {
|
statuses: {
|
||||||
passing: (item, value) => item.Status === value,
|
passing: (item, value) => item.Status === value,
|
||||||
warning: (item, value) => item.Status === value,
|
warning: (item, value) => item.Status === value,
|
||||||
critical: (item, value) => item.Status === value,
|
critical: (item, value) => item.Status === value,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import setHelpers from 'mnemonist/set';
|
export default {
|
||||||
import { andOr } from 'consul-ui/utils/filter';
|
|
||||||
|
|
||||||
export default andOr({
|
|
||||||
kinds: {
|
kinds: {
|
||||||
'global-management': (item, value) => item.isGlobalManagement,
|
'global-management': (item, value) => item.isGlobalManagement,
|
||||||
standard: (item, value) => !item.isGlobalManagement,
|
standard: (item, value) => !item.isGlobalManagement,
|
||||||
|
@ -12,4 +9,4 @@ export default andOr({
|
||||||
setHelpers.intersectionSize(values, new Set(item.Datacenters)) > 0
|
setHelpers.intersectionSize(values, new Set(item.Datacenters)) > 0
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import setHelpers from 'mnemonist/set';
|
import setHelpers from 'mnemonist/set';
|
||||||
import { andOr } from 'consul-ui/utils/filter';
|
|
||||||
|
|
||||||
export default andOr({
|
export default {
|
||||||
statuses: {
|
statuses: {
|
||||||
passing: (item, value) => item.Status === value,
|
passing: (item, value) => item.Status === value,
|
||||||
warning: (item, value) => item.Status === value,
|
warning: (item, value) => item.Status === value,
|
||||||
|
@ -10,4 +9,4 @@ export default andOr({
|
||||||
sources: (item, values) => {
|
sources: (item, values) => {
|
||||||
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import setHelpers from 'mnemonist/set';
|
import setHelpers from 'mnemonist/set';
|
||||||
import { andOr } from 'consul-ui/utils/filter';
|
|
||||||
|
|
||||||
export default andOr({
|
export default {
|
||||||
kinds: {
|
kinds: {
|
||||||
'ingress-gateway': (item, value) => item.Kind === value,
|
'ingress-gateway': (item, value) => item.Kind === value,
|
||||||
'terminating-gateway': (item, value) => item.Kind === value,
|
'terminating-gateway': (item, value) => item.Kind === value,
|
||||||
|
@ -22,4 +21,4 @@ export default andOr({
|
||||||
sources: (item, values) => {
|
sources: (item, values) => {
|
||||||
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import setHelpers from 'mnemonist/set';
|
export default {
|
||||||
import { andOr } from 'consul-ui/utils/filter';
|
|
||||||
|
|
||||||
export default andOr({
|
|
||||||
kinds: {
|
kinds: {
|
||||||
'global-management': (item, value) => item.isGlobalManagement,
|
'global-management': (item, value) => item.isGlobalManagement,
|
||||||
global: (item, value) => !item.Local,
|
global: (item, value) => !item.Local,
|
||||||
local: (item, value) => item.Local,
|
local: (item, value) => item.Local,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
|
@ -25,6 +25,11 @@ export default class Kv extends Model {
|
||||||
@attr('number') ModifyIndex;
|
@attr('number') ModifyIndex;
|
||||||
@attr('string') Session;
|
@attr('string') Session;
|
||||||
|
|
||||||
|
@computed('isFolder')
|
||||||
|
get Kind() {
|
||||||
|
return this.isFolder ? 'folder' : 'key';
|
||||||
|
}
|
||||||
|
|
||||||
@computed('Key')
|
@computed('Key')
|
||||||
get isFolder() {
|
get isFolder() {
|
||||||
return isFolder(this.Key || '');
|
return isFolder(this.Key || '');
|
||||||
|
|
|
@ -20,6 +20,8 @@ export default class ServiceInstance extends Model {
|
||||||
@attr() meta;
|
@attr() meta;
|
||||||
|
|
||||||
@or('Service.ID', 'Service.Service') Name;
|
@or('Service.ID', 'Service.Service') Name;
|
||||||
|
@or('Service.Address', 'Node.Service') Address;
|
||||||
|
|
||||||
@alias('Service.Tags') Tags;
|
@alias('Service.Tags') Tags;
|
||||||
@alias('Service.Meta') Meta;
|
@alias('Service.Meta') Meta;
|
||||||
@alias('Service.Namespace') Namespace;
|
@alias('Service.Namespace') Namespace;
|
||||||
|
|
|
@ -6,13 +6,13 @@ import { get } from '@ember/object';
|
||||||
import WithAclActions from 'consul-ui/mixins/acl/with-actions';
|
import WithAclActions from 'consul-ui/mixins/acl/with-actions';
|
||||||
|
|
||||||
export default class IndexRoute extends Route.extend(WithAclActions) {
|
export default class IndexRoute extends Route.extend(WithAclActions) {
|
||||||
@service('repository/acl')
|
@service('repository/acl') repo;
|
||||||
repo;
|
|
||||||
|
|
||||||
@service('settings')
|
@service('settings') settings;
|
||||||
settings;
|
|
||||||
|
|
||||||
queryParams = {
|
queryParams = {
|
||||||
|
sortBy: 'sort',
|
||||||
|
kind: 'kind',
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -11,6 +11,10 @@ export default class IndexRoute extends Route.extend(WithPolicyActions) {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
dc: 'dc',
|
dc: 'dc',
|
||||||
kind: 'kind',
|
kind: 'kind',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Description']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -9,6 +9,10 @@ export default class IndexRoute extends Route.extend(WithRoleActions) {
|
||||||
|
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Description', 'Policy']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -11,6 +11,10 @@ export default class IndexRoute extends Route.extend(WithTokenActions) {
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
kind: 'kind',
|
kind: 'kind',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['AccessorID', 'Description', 'Role', 'Policy']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -4,6 +4,10 @@ export default class IndexRoute extends Route {
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
access: 'access',
|
access: 'access',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['SourceName', 'DestinationName']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -9,6 +9,7 @@ export default class IndexRoute extends Route {
|
||||||
|
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
|
kind: 'kind',
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -8,6 +8,10 @@ export default class IndexRoute extends Route {
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
status: 'status',
|
status: 'status',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Node', 'Address', 'Meta']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -9,6 +9,10 @@ export default class IndexRoute extends Route.extend(WithNspaceActions) {
|
||||||
|
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Description', 'Role', 'Policy']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -10,6 +10,10 @@ export default class IndexRoute extends Route {
|
||||||
status: 'status',
|
status: 'status',
|
||||||
source: 'source',
|
source: 'source',
|
||||||
kind: 'kind',
|
kind: 'kind',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Tags']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
@ -17,26 +21,11 @@ export default class IndexRoute extends Route {
|
||||||
};
|
};
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
let terms = params.s || '';
|
|
||||||
// we check for the old style `status` variable here
|
|
||||||
// and convert it to the new style filter=status:critical
|
|
||||||
let status = params.status;
|
|
||||||
if (status) {
|
|
||||||
status = `status:${status}`;
|
|
||||||
if (terms.indexOf(status) === -1) {
|
|
||||||
terms = terms
|
|
||||||
.split('\n')
|
|
||||||
.concat(status)
|
|
||||||
.join('\n')
|
|
||||||
.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const nspace = this.modelFor('nspace').nspace.substr(1);
|
const nspace = this.modelFor('nspace').nspace.substr(1);
|
||||||
const dc = this.modelFor('dc').dc.Name;
|
const dc = this.modelFor('dc').dc.Name;
|
||||||
return hash({
|
return hash({
|
||||||
nspace: nspace,
|
nspace: nspace,
|
||||||
dc: dc,
|
dc: dc,
|
||||||
terms: terms !== '' ? terms.split('\n') : [],
|
|
||||||
items: this.data.source(uri => uri`/${nspace}/${dc}/services`),
|
items: this.data.source(uri => uri`/${nspace}/${dc}/services`),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,10 @@ export default class InstancesRoute extends Route {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
status: 'status',
|
status: 'status',
|
||||||
source: 'source',
|
source: 'source',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Tags', 'ID', 'Address', 'Port', 'Service.Meta', 'Node.Meta']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -4,6 +4,10 @@ export default class IndexRoute extends Route {
|
||||||
queryParams = {
|
queryParams = {
|
||||||
sortBy: 'sort',
|
sortBy: 'sort',
|
||||||
access: 'access',
|
access: 'access',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['SourceName', 'DestinationName']],
|
||||||
|
},
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -3,8 +3,20 @@ import Route from 'consul-ui/routing/route';
|
||||||
import { hash } from 'rsvp';
|
import { hash } from 'rsvp';
|
||||||
|
|
||||||
export default class ServicesRoute extends Route {
|
export default class ServicesRoute extends Route {
|
||||||
@service('data-source/service')
|
@service('data-source/service') data;
|
||||||
data;
|
|
||||||
|
queryParams = {
|
||||||
|
sortBy: 'sort',
|
||||||
|
instance: 'instance',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Tags']],
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
as: 'filter',
|
||||||
|
replace: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
model() {
|
model() {
|
||||||
const dc = this.modelFor('dc').dc.Name;
|
const dc = this.modelFor('dc').dc.Name;
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
import Route from './services';
|
import Route from './services';
|
||||||
|
|
||||||
export default class UpstreamsRoute extends Route {
|
export default class UpstreamsRoute extends Route {
|
||||||
|
queryParams = {
|
||||||
|
sortBy: 'sort',
|
||||||
|
instance: 'instance',
|
||||||
|
searchproperty: {
|
||||||
|
as: 'searchproperty',
|
||||||
|
empty: [['Name', 'Tags']],
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
as: 'filter',
|
||||||
|
replace: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
templateName = 'dc/services/show/upstreams';
|
templateName = 'dc/services/show/upstreams';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
import { setProperties } from '@ember/object';
|
import { get, setProperties } from '@ember/object';
|
||||||
|
|
||||||
// paramsFor
|
// paramsFor
|
||||||
import { routes } from 'consul-ui/router';
|
import { routes } from 'consul-ui/router';
|
||||||
|
@ -7,6 +7,37 @@ import wildcard from 'consul-ui/utils/routing/wildcard';
|
||||||
const isWildcard = wildcard(routes);
|
const isWildcard = wildcard(routes);
|
||||||
|
|
||||||
export default class BaseRoute extends Route {
|
export default class BaseRoute extends Route {
|
||||||
|
/**
|
||||||
|
* By default any empty string query parameters should remove the query
|
||||||
|
* parameter from the URL. This is the most common behavior if you don't
|
||||||
|
* require this behavior overwrite this method in the specific Route for the
|
||||||
|
* specific queryParam key.
|
||||||
|
* If the behaviour should be different add an empty: [] parameter to the
|
||||||
|
* queryParameter configuration to configure what is deemed 'empty'
|
||||||
|
*/
|
||||||
|
serializeQueryParam(value, key, type) {
|
||||||
|
if(typeof value !== 'undefined') {
|
||||||
|
const empty = get(this, `queryParams.${key}.empty`);
|
||||||
|
if(typeof empty === 'undefined') {
|
||||||
|
// by default any queryParams when an empty string mean undefined,
|
||||||
|
// therefore remove the queryParam from the URL
|
||||||
|
if(value === '') {
|
||||||
|
value = undefined;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const possible = empty[0];
|
||||||
|
let actual = value;
|
||||||
|
if(Array.isArray(actual)) {
|
||||||
|
actual = actual.split(',');
|
||||||
|
}
|
||||||
|
const diff = possible.filter(item => !actual.includes(item))
|
||||||
|
if(diff.length === 0) {
|
||||||
|
value = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Set the routeName for the controller so that it is available in the template
|
* Set the routeName for the controller so that it is available in the template
|
||||||
* for the route/controller.. This is mainly used to give a route name to the
|
* for the route/controller.. This is mainly used to give a route name to the
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const sLower = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Name')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
get(item, 'ID')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
import rightTrim from 'consul-ui/utils/right-trim';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const key = rightTrim(get(item, 'Key'), '/')
|
|
||||||
.split('/')
|
|
||||||
.pop();
|
|
||||||
return key.toLowerCase().indexOf(s.toLowerCase()) !== -1;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const sLower = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Node')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
get(item, 'Address')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { get } from '@ember/object';
|
|
||||||
export default function(filterable) {
|
|
||||||
return filterable(function(item, { s = '' }) {
|
|
||||||
const sLower = s.toLowerCase();
|
|
||||||
return (
|
|
||||||
get(item, 'Name')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
get(item, 'Description')
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(sLower) !== -1 ||
|
|
||||||
(get(item, 'ACLs.PolicyDefaults') || []).some(function(item) {
|
|
||||||
return item.Name.toLowerCase().indexOf(sLower) !== -1;
|
|
||||||
}) ||
|
|
||||||
(get(item, 'ACLs.RoleDefaults') || []).some(function(item) {
|
|
||||||
return item.Name.toLowerCase().indexOf(sLower) !== -1;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue