ui: Search/filtering 'Filtered by:' search status (#9442)
Adds a 'status' for the filtering/searching in the UI, without this its not super clear that you are filtering a recordset due to the menu selections being hidden once closed. You can also use the pills in this status view to delete individual filters.
This commit is contained in:
parent
e3f5a77ade
commit
148b18b28c
|
@ -0,0 +1,4 @@
|
|||
```release-note:feature
|
||||
ui: Add additional search/filter status pills for viewing and removing current
|
||||
filters in listing views
|
||||
```
|
|
@ -31,6 +31,8 @@ module.exports = {
|
|||
|
||||
'no-unnecessary-component-helper': false,
|
||||
'link-href-attributes': false,
|
||||
// we need to be able to say tabindex={{@tabindex}}
|
||||
'no-positive-tabindex': false,
|
||||
|
||||
'no-bare-strings': false,
|
||||
},
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
{{~/if~}}
|
||||
{{~else~}}
|
||||
<button
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
{{on 'click' (optional @onclick)}}
|
||||
tabindex={{@tabindex}}
|
||||
...attributes
|
||||
>{{yield}}</button>
|
||||
{{~/if}}
|
|
@ -14,6 +14,7 @@
|
|||
<YieldSlot @name="confirm" @params={{
|
||||
block-params (component 'action'
|
||||
onclick=(action @onclick)
|
||||
tabindex="-1"
|
||||
)
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -1,59 +1,127 @@
|
|||
<form
|
||||
class="consul-acl-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-acl-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<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>
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.acl.search-bar." search.status.key)
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.acl.search-bar." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/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>
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
{{#if @filter.searchproperty}}
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @filter.kind.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "components.consul.acl.search-bar.kind.name"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each (array "management" "client") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.status.value}}>
|
||||
{{t (concat "components.acl.search-bar.kind.options." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.consul.name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,140 +1,190 @@
|
|||
<form
|
||||
class="consul-health-check-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-healthcheck-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.health-check.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.health-check.search-bar." search.status.key ".options." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
{{#if @filter.searchproperty}}
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @filter.status.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "common.consul.status"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @searchproperties as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperties}}>{{prop}}</Option>
|
||||
{{#each (array "passing" "warning" "critical" "empty") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.status.value}}>
|
||||
{{t (concat "common.consul." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.status}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Health Status
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
</search.Select>
|
||||
{{#if @filter.kind}}
|
||||
<search.Select
|
||||
class="type-kind"
|
||||
@position="left"
|
||||
@onchange={{action @filter.kind.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "components.consul.health-check.search-bar.kind.name"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each (array "service" "node") as |item|}}
|
||||
<Option @value={{item}} @selected={{contains item @filter.kind.value}}>
|
||||
{{t (concat "components.consul.health-check.search-bar.kind.options." item)
|
||||
default=(array
|
||||
(concat "common.search." item)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
<search.Select
|
||||
class="type-check"
|
||||
@position="left"
|
||||
@onchange={{action @filter.check.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "components.consul.health-check.search-bar.check.name"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each (array "alias" "docker" "grpc" "http" "script" "serf" "tcp" "ttl") as |item|}}
|
||||
<Option @value={{item}} @selected={{contains item @filter.check.value}}>
|
||||
{{t (concat "components.consul.health-check.search-bar.check.options." item)
|
||||
default=(array
|
||||
(concat "common.search." item)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
(array "Status:asc" (t "common.sort.status.asc"))
|
||||
(array "Status:desc" (t "common.sort.status.desc"))
|
||||
(array "Kind:asc" (t "components.consul.health-check.search-bar.sort.kind.asc"))
|
||||
(array "Kind:desc" (t "components.consul.health-check.search-bar.sort.kind.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup 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-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</Option>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
|
||||
<PopoverSelect
|
||||
class="type-kind"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.kind}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Kind
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Option @value="service" @selected={{contains 'service' @filter.kinds}}>Service Check</Option>
|
||||
<Option @value="node" @selected={{contains 'node' @filter.kinds}}>Node Check</Option>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
|
||||
<PopoverSelect
|
||||
class="type-check"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.check}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Type
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Option @value="alias" @selected={{contains 'alias' @filter.checks}}>alias</Option>
|
||||
<Option @value="docker" @selected={{contains 'docker' @filter.checks}}>Docker</Option>
|
||||
<Option @value="grpc" @selected={{contains 'grpc' @filter.checks}}>gRPC</Option>
|
||||
<Option @value="http" @selected={{contains 'http' @filter.checks}}>HTTP</Option>
|
||||
<Option @value="serf" @selected={{contains 'serf' @filter.checks}}>Serf</Option>
|
||||
<Option @value="tcp" @selected={{contains 'tcp' @filter.checks}}>TCP</Option>
|
||||
<Option @value="ttl" @selected={{contains 'ttl' @filter.checks}}>TTL</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")
|
||||
(array "Status:asc" "Unhealthy to Healthy")
|
||||
(array "Status:desc" "Healthy to Unhealthy")
|
||||
(array "Kind:asc" "Service to Node")
|
||||
(array "Kind:desc" "Node to Service")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Health Status">
|
||||
<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>
|
||||
<Optgroup @label={{t "common.consul.status"}}>
|
||||
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort.value}}>{{t "common.sort.status.asc"}}</Option>
|
||||
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort.value}}>{{t "common.sort.status.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Check Name">
|
||||
<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>
|
||||
<Optgroup @label={{t "components.consul.health-check.search-bar.sort.name.name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Check Type">
|
||||
<Optgroup @label={{t "components.consul.health-check.search-bar.sort.kind.name"}}>
|
||||
<Option @value="Kind:asc" @selected={{eq "Kind:asc" @sort}}>Service to Node</Option>
|
||||
<Option @value="Kind:desc" @selected={{eq "Kind:desc" @sort}}>Node to Service</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
|
@ -1,102 +1,140 @@
|
|||
<form
|
||||
class="consul-intention-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-intention-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.intention.search-bar." search.status.key)
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.intention.search-bar." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
{{#if @filter.searchproperty}}
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-access"
|
||||
@position="left"
|
||||
@onchange={{action @filter.access.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "components.consul.intention.search-bar.access.name"}}
|
||||
</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>
|
||||
{{#each (array "allow" "deny" "") as |item|}}
|
||||
<Option class={{concat 'value-' item}} @value={{or item 'app-aware'}} @selected={{contains (or item 'app-aware') @filter.access.value}}>
|
||||
<span>{{t (concat "components.consul.intention.search-bar.access.options." (or item 'app-aware'))}}</span>
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.access}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Permission
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Option class="value-allow" @value="allow" @selected={{contains 'allow'
|
||||
@filter.accesses}}><span>Allow</span></Option>
|
||||
<Option class="value-deny" @value="deny" @selected={{contains 'deny'
|
||||
@filter.accesses}}><span>Deny</span></Option>
|
||||
<Option class="value-" @value="app-aware" @selected={{contains
|
||||
'app-aware' @filter.accesses}}><span>App aware</span></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 "Action:asc" "Allow to Deny")
|
||||
(array "Action:desc" "Deny to Allow")
|
||||
(array "SourceName:asc" "Source: A to Z")
|
||||
(array "SourceName:desc" "Source: Z to A")
|
||||
(array "DestinationName:asc" "Destination: A to Z")
|
||||
(array "DestinationName:desc" "Destination: Z to A")
|
||||
(array "Precedence:asc" "Precedence: Ascending")
|
||||
(array "Precedence:desc" "Precedence: Descending")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Permission">
|
||||
<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>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Action:asc" (t "components.consul.intention.search-bar.sort.access.asc"))
|
||||
(array "Action:desc" (t "components.consul.intention.search-bar.sort.access.desc"))
|
||||
(array "SourceName:asc" (t "components.consul.intention.search-bar.sort.source-name.asc"))
|
||||
(array "SourceName:desc" (t "components.consul.intention.search-bar.sort.source-name.desc"))
|
||||
(array "DestinationName:asc" (t "components.consul.intention.search-bar.sort.destination-name.asc"))
|
||||
(array "DestinationName:desc" (t "components.consul.intention.search-bar.sort.destination-name.desc"))
|
||||
(array "Precedence:asc" (t "common.sort.numeric.asc"))
|
||||
(array "Precedence:desc" (t "common.sort.numeric.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "components.consul.intention.search-bar.sort.access.name"}}>
|
||||
<Option @value="Action:asc" @selected={{eq "Action:asc" @sort.value}}>{{t "components.consul.intention.search-bar.sort.access.asc"}}</Option>
|
||||
<Option @value="Action:desc" @selected={{eq "Action:desc" @sort.value}}>{{t "components.consul.intention.search-bar.sort.access.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Source">
|
||||
<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>
|
||||
<Optgroup @label={{t "components.consul.intention.search-bar.sort.source-name.name"}}>
|
||||
<Option @value="SourceName:asc" @selected={{eq "SourceName:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="SourceName:desc" @selected={{eq "SourceName:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Destination">
|
||||
<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>
|
||||
<Optgroup @label={{t "components.consul.intention.search-bar.sort.destination-name.name"}}>
|
||||
<Option @value="DestinationName:asc" @selected={{eq "DestinationName:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="DestinationName:desc" @selected={{eq "DestinationName:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Precedence">
|
||||
<Option @value="Precedence:asc" @selected={{eq "Precedence:asc" @sort}}>Ascending</Option>
|
||||
<Option @value="Precedence:desc" @selected={{eq "Precedence:desc" @sort}}>Descending</Option>
|
||||
<Optgroup @label={{t "components.consul.intention.search-bar.sort.precedence.name"}}>
|
||||
<Option @value="Precedence:asc" @selected={{eq "Precedence:asc" @sort.value}}>{{t "common.sort.numeric.asc"}}</Option>
|
||||
<Option @value="Precedence:desc" @selected={{eq "Precedence:desc" @sort.value}}>{{t "common.sort.numeric.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
|
@ -1,68 +1,128 @@
|
|||
<form
|
||||
class="consul-kv-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-kv-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<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>
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.kv.search-bar." search.status.key)
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.kv.search-bar." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/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>
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
{{#if @filter.searchproperty}}
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-kind"
|
||||
@position="left"
|
||||
@onchange={{action @filter.kind.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "components.consul.kv.search-bar.kind.name"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each (array "folder" "key") as |item|}}
|
||||
<Option class="value-{item}}" @value={{item}} @selected={{contains item @filter.kind.value}}>
|
||||
{{t (concat "components.consul.kv.search-bar.kind.options." item)}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Key:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Key:desc" (t "common.sort.alpha.desc"))
|
||||
(array "Kind:asc" (t "components.consul.kv.search-bar.sort.kind.asc"))
|
||||
(array "Kind:desc" (t "components.consul.kv.search-bar.sort.kind.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.consul.name"}}>
|
||||
<Option @value="Key:asc" @selected={{eq "Key:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Key:desc" @selected={{eq "Key:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label={{t "components.consul.kv.search-bar.kind.name"}}>
|
||||
<Option @value="Kind:asc" @selected={{eq "Kind:asc" @sort.value}}>{{t "components.consul.kv.search-bar.sort.kind.asc"}}</Option>
|
||||
<Option @value="Kind:desc" @selected={{eq "Kind:desc" @sort.value}}>{{t "components.consul.kv.search-bar.sort.kind.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,90 +1,131 @@
|
|||
<form
|
||||
class="consul-node-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-node-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.node.search-bar." search.status.key)
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.node.search-bar." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @filter.status.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "common.consul.status"}}
|
||||
</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>
|
||||
{{#each (array "passing" "warning" "critical") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.status.value}}>
|
||||
{{t (concat "common.consul." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.status}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Health Status
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup 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-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</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 "Node:asc" "A to Z")
|
||||
(array "Node:desc" "Z to A")
|
||||
(array "Status:asc" "Unhealthy to Healthy")
|
||||
(array "Status:desc" "Healthy to Unhealthy")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Health Status">
|
||||
<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>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Service Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Node:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Node:desc" (t "common.sort.alpha.desc"))
|
||||
(array "Status:asc" (t "common.sort.status.asc"))
|
||||
(array "Status:desc" (t "common.sort.status.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.consul.status"}}>
|
||||
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort.value}}>{{t "common.sort.status.asc"}}</Option>
|
||||
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort.value}}>{{t "common.sort.status.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label={{t "common.consul.node-name"}}>
|
||||
<Option @value="Node:asc" @selected={{eq "Node:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Node:desc" @selected={{eq "Node:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
|
@ -1,63 +1,98 @@
|
|||
<form
|
||||
class="consul-nspace-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-nspace-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.nspace.search-bar." search.status.key)
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.nspace.search-bar." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
@multiple={{true}}
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</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>
|
||||
<Optgroup @label={{t "common.consul.name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</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|}}
|
||||
<Optgroup @label="Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
|
@ -1,101 +1,145 @@
|
|||
<form
|
||||
class="consul-policy-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-policy-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.policy.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.policy.search-bar." search.status.key ".options." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{if (eq search.status.key 'datacenter') search.status.value value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-datacenter"
|
||||
@position="left"
|
||||
@onchange={{action @filter.datacenter.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "common.consul.datacenter"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each dcs as |dc|}}
|
||||
<Option @value={{dc.Name}} @selected={{contains dc.Name @filter.datacenter.value}}>{{dc.Name}}</Option>
|
||||
{{/each}}
|
||||
<DataSource @src="/*/*/datacenters" @loading="lazy" @onchange={{action (mut this.dcs) value="data"}} />
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
<search.Select
|
||||
class="type-kind"
|
||||
@position="left"
|
||||
@onchange={{action @filter.kind.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "components.consul.policy.search-bar.kind.name"}}
|
||||
</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>
|
||||
{{#each (array "global-management" "standard") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.kind.value}}>
|
||||
{{t (concat "components.consul.policy.search-bar.kind.options." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
class="select-dcs"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.dc}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Datacenters
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each dcs as |dc|}}
|
||||
<Option @value={{@dc.Name}} @selected={{contains dc.Name @filter.dcs}}>{{dc.Name}}</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
<DataSource @src="/*/*/datacenters" @loading="lazy" @onchange={{action (mut this.dcs) value="data"}} />
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
<PopoverSelect
|
||||
class="select-type"
|
||||
@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="global-management" @selected={{contains 'global-management' @filter.kinds}}>Global Management</Option>
|
||||
<Option @value="standard" @selected={{contains 'standard' @filter.kinds}}>Standard</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|}}
|
||||
<Optgroup @label="Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.ui.name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,68 +1,104 @@
|
|||
<form
|
||||
class="consul-role-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-role-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.role.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.role.search-bar." search.status.key ".options." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
@multiple={{true}}
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
(array "CreateIndex:desc" (t "common.sort.age.desc"))
|
||||
(array "CreateIndex:asc" (t "common.sort.age.asc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</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>
|
||||
<Optgroup @label={{t "common.ui.name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label={{t "common.ui.creation"}}>
|
||||
<Option @value="CreateIndex:desc" @selected={{eq "CreateIndex:desc" @sort.value}}>{{t "common.sort.age.desc"}}</Option>
|
||||
<Option @value="CreateIndex:asc" @selected={{eq "CreateIndex:asc" @sort.value}}>{{t "common.sort.age.asc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</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")
|
||||
(array "CreateIndex:desc" "Newest to oldest")
|
||||
(array "CreateIndex:asc" "Oldest to newest")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Creation">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,111 +1,156 @@
|
|||
<form
|
||||
class="consul-service-instance-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-service-instance-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.service-instance.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.service-instance.search-bar." search.status.key ".options." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
{{#if @filter.searchproperty}}
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @filter.status.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "common.consul.status"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @searchproperties as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperties}}>{{string-replace-all prop '\.' ' '}}</Option>
|
||||
{{#each (array "passing" "warning" "critical" "empty") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.status.value}}>
|
||||
{{t (concat "common.consul." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.status}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Health Status
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
</search.Select>
|
||||
{{#if (gt @sources.length 0)}}
|
||||
<search.Select
|
||||
class="type-source"
|
||||
@position="left"
|
||||
@onchange={{action @filter.source.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.source"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @sources as |source|}}
|
||||
<Option class={{source}} @value={{source}} @selected={{contains source @filter.source.value}}>
|
||||
{{t (concat "common.brand." source)}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
(array "Status:asc" (t "common.sort.status.asc"))
|
||||
(array "Status:desc" (t "common.sort.status.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup 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-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</Option>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
{{#if (gt @sources.length 0)}}
|
||||
<PopoverSelect
|
||||
class="type-source"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.source}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Source
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @sources as |source|}}
|
||||
<Option class={{source}} @value={{source}} @selected={{contains source @filter.sources}}>{{source}}</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
{{/if}}
|
||||
</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")
|
||||
(array "Status:asc" "Unhealthy to Healthy")
|
||||
(array "Status:desc" "Healthy to Unhealthy")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Health Status">
|
||||
<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>
|
||||
<Optgroup @label={{t "common.consul.status"}}>
|
||||
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort.value}}>{{t "common.sort.status.asc"}}</Option>
|
||||
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort.value}}>{{t "common.sort.status.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Service Name">
|
||||
<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>
|
||||
<Optgroup @label={{t "components.consul.service-instance.search-bar.sort.name.name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,135 +1,190 @@
|
|||
<form
|
||||
class="consul-service-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-service-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.service.search-bar." search.status.key)
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.service.search-bar." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @filter.status.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "common.consul.status"}}
|
||||
</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>
|
||||
{{#each (array "passing" "warning" "critical" "empty") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.status.value}}>
|
||||
{{t (concat "common.consul." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.status}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Health Status
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup 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-critical" @value="critical" @selected={{contains 'critical' @filter.statuses}}>Failing</Option>
|
||||
<Option class="value-empty" @value="empty" @selected={{contains 'empty' @filter.statuses}}>No checks</Option>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
<PopoverSelect
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.kind}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Service Type
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Option @value="service" @selected={{contains 'service' @filter.kinds}}>Service</Option>
|
||||
<Optgroup @label="Gateway">
|
||||
<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="mesh-gateway" @selected={{contains 'mesh-gateway' @filter.kinds}}>Mesh Gateway</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Mesh">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
{{#if (gt @sources.length 0)}}
|
||||
<PopoverSelect
|
||||
class="type-source"
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.source}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Source
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @sources as |source|}}
|
||||
<Option class={{source}} @value={{source}} @selected={{contains source @filter.sources}}>{{source}}</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
{{/if}}
|
||||
</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")
|
||||
(array "Status:asc" "Unhealthy to Healthy")
|
||||
(array "Status:desc" "Healthy to Unhealthy")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Health Status">
|
||||
<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>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Service Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
<search.Select
|
||||
@position="left"
|
||||
@onchange={{action @filter.kind.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "components.consul.service.search-bar.kind"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Option @value="service" @selected={{contains 'service' @filter.kind.value}}>
|
||||
{{t "common.consul.service"}}
|
||||
</Option>
|
||||
<Optgroup
|
||||
@label={{t "common.consul.gateway"}}
|
||||
>
|
||||
{{#each (array "ingress-gateway" "terminating-gateway" "mesh-gateway") as |kind|}}
|
||||
<Option @value={{kind}} @selected={{contains kind @filter.kind.value}}>
|
||||
{{t (concat "common.consul." kind)}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
</Optgroup>
|
||||
<Optgroup
|
||||
@label={{t "common.consul.mesh"}}
|
||||
>
|
||||
{{#each (array "in-mesh" "not-in-mesh") as |state|}}
|
||||
<Option @value={{state}} @selected={{contains state @filter.kind.value}}>
|
||||
{{t (concat "common.search." state)}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{#if (gt @sources.length 0)}}
|
||||
<search.Select
|
||||
class="type-source"
|
||||
@position="left"
|
||||
@onchange={{action @filter.source.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.source"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @sources as |source|}}
|
||||
<Option class={{source}} @value={{source}} @selected={{contains source @filter.source.value}}>
|
||||
{{t (concat "common.brand." source)}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
{{/if}}
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
(array "Status:asc" (t "common.sort.status.asc"))
|
||||
(array "Status:desc" (t "common.sort.status.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.consul.status"}}>
|
||||
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort.value}}>{{t "common.sort.status.asc"}}</Option>
|
||||
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort.value}}>{{t "common.sort.status.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label={{t "common.consul.service-name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,83 +1,125 @@
|
|||
<form
|
||||
class="consul-token-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-token-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.token.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.token.search-bar." search.status.key ".options." search.status.value)
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
class="type-status"
|
||||
@position="left"
|
||||
@onchange={{action @filter.kind.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "components.consul.token.search-bar.kind.name"}}
|
||||
</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>
|
||||
{{#each (array "global-management" "global" "local") as |state|}}
|
||||
<Option class="value-{{state}}" @value={{state}} @selected={{contains state @filter.kind.value}}>
|
||||
{{t (concat "components.consul.token.search-bar.kind.options." state)
|
||||
default=(array
|
||||
(concat "common.search." state)
|
||||
)
|
||||
}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</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="global-management" @selected={{contains 'global-management' @filter.kinds}}>Global Management</Option>
|
||||
<Option @value="global" @selected={{contains 'global' @filter.kinds}}>Global Scope</Option>
|
||||
<Option @value="local" @selected={{contains 'local' @filter.kinds}}>Local Scope</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 "CreateTime:desc" "Newest to oldest")
|
||||
(array "CreateTime:asc" "Oldest to newest")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Creation">
|
||||
<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>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "CreateTime:desc" (t "common.sort.age.desc"))
|
||||
(array "CreateTime:asc" (t "common.sort.age.asc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.ui.creation"}}>
|
||||
<Option @value="CreateTime:desc" @selected={{eq "CreateTime:desc" @sort.value}}>{{t "common.sort.age.desc"}}</Option>
|
||||
<Option @value="CreateTime:asc" @selected={{eq "CreateTime:asc" @sort.value}}>{{t "common.sort.age.asc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,63 +1,96 @@
|
|||
<form
|
||||
class="consul-upstream-instance-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-upstream-instance-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.upstream-instance.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.upstream-instance.search-bar." search.status.value ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
@multiple={{true}}
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{#let (from-entries (array
|
||||
(array "DestinationName:asc" (t "common.sort.alpha.asc"))
|
||||
(array "DestinationName:desc" (t "common.sort.alpha.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @searchproperties as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperties}}>{{prop}}</Option>
|
||||
{{/each}}
|
||||
<Option @value="DestinationName:asc" @selected={{eq "DestinationName:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="DestinationName:desc" @selected={{eq "DestinationName:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="sort">
|
||||
{{#let (or @sort 'DestinationName:asc') as |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 "DestinationName:asc" "A to Z")
|
||||
(array "DestinationName:desc" "Z to A")
|
||||
))
|
||||
as |selectable|}}
|
||||
{{get selectable sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Service Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
{{/let}}
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,86 +1,126 @@
|
|||
<form
|
||||
class="consul-upstream-search-bar filter-bar"
|
||||
<SearchBar
|
||||
class="consul-upstream-search-bar"
|
||||
...attributes
|
||||
@filter={{@filter}}
|
||||
>
|
||||
<div class="search">
|
||||
<FreetextFilter
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder="Search"
|
||||
>
|
||||
<PopoverSelect
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @onfilter.searchproperty}}
|
||||
<:status as |search|>
|
||||
|
||||
{{#let
|
||||
|
||||
(t (concat "components.consul.upstream.search-bar." search.status.key ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.key)
|
||||
(concat "common.consul." search.status.key)
|
||||
)
|
||||
)
|
||||
|
||||
(t (concat "components.consul.upstream.search-bar." search.status.value ".name")
|
||||
default=(array
|
||||
(concat "common.search." search.status.value)
|
||||
(concat "common.consul." search.status.value)
|
||||
(concat "common.brand." search.status.value)
|
||||
)
|
||||
)
|
||||
|
||||
as |key value|}}
|
||||
<search.RemoveFilter
|
||||
aria-label={{t "common.ui.remove" item=(concat key " " value)}}
|
||||
>
|
||||
<dl>
|
||||
<dt>{{key}}</dt>
|
||||
<dd>{{value}}</dd>
|
||||
</dl>
|
||||
</search.RemoveFilter>
|
||||
{{/let}}
|
||||
|
||||
</:status>
|
||||
<:search as |search|>
|
||||
<search.Search
|
||||
@onsearch={{action @onsearch}}
|
||||
@value={{@search}}
|
||||
@placeholder={{t "common.search.search"}}
|
||||
>
|
||||
<search.Select
|
||||
class="type-search-properties"
|
||||
@position="right"
|
||||
@onchange={{action @filter.searchproperty.change}}
|
||||
@multiple={{true}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{t "common.search.searchproperty"}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
{{#each @filter.searchproperty.default as |prop|}}
|
||||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperty.value}}>
|
||||
{{t (concat "common.consul." (lowercase prop))}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</search.Search>
|
||||
</:search>
|
||||
<:filter as |search|>
|
||||
<search.Select
|
||||
@position="left"
|
||||
@onchange={{action @filter.instance.change}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Search across
|
||||
{{t "components.consul.upstream.search-bar.instance.name"}}
|
||||
</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>
|
||||
{{#each (array "registered" "not-registered") as |item|}}
|
||||
<Option @value={{item}} @selected={{contains item @filter.instance.value}}>
|
||||
{{t (concat "common.consul." item)}}
|
||||
</Option>
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</FreetextFilter>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<PopoverSelect
|
||||
@position="left"
|
||||
@onchange={{action @onfilter.instance}}
|
||||
@multiple={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
Type
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Option @value="registered" @selected={{contains 'registered' @filter.instances}}>Registered</Option>
|
||||
<Option @value="not-registered" @selected={{contains 'not-registered' @filter.instances}}>Not Registered</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")
|
||||
(array "Status:asc" "Unhealthy to Healthy")
|
||||
(array "Status:desc" "Healthy to Unhealthy")
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label="Health Status">
|
||||
<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>
|
||||
</Optgroup>
|
||||
<Optgroup @label="Service Name">
|
||||
<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>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</PopoverSelect>
|
||||
</div>
|
||||
</form>
|
||||
</search.Select>
|
||||
</:filter>
|
||||
<:sort as |search|>
|
||||
<search.Select
|
||||
class="type-sort"
|
||||
data-test-sort-control
|
||||
@position="right"
|
||||
@onchange={{action @sort.change}}
|
||||
@multiple={{false}}
|
||||
@required={{true}}
|
||||
as |components|>
|
||||
<BlockSlot @name="selected">
|
||||
<span>
|
||||
{{#let (from-entries (array
|
||||
(array "Name:asc" (t "common.sort.alpha.asc"))
|
||||
(array "Name:desc" (t "common.sort.alpha.desc"))
|
||||
(array "Status:asc" (t "common.sort.status.asc"))
|
||||
(array "Status:desc" (t "common.sort.status.desc"))
|
||||
))
|
||||
as |selectable|
|
||||
}}
|
||||
{{get selectable @sort.value}}
|
||||
{{/let}}
|
||||
</span>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="options">
|
||||
{{#let components.Optgroup components.Option as |Optgroup Option|}}
|
||||
<Optgroup @label={{t "common.consul.status"}}>
|
||||
<Option @value="Status:asc" @selected={{eq "Status:asc" @sort.value}}>{{t "common.sort.status.asc"}}</Option>
|
||||
<Option @value="Status:desc" @selected={{eq "Status:desc" @sort.value}}>{{t "common.sort.status.desc"}}</Option>
|
||||
</Optgroup>
|
||||
<Optgroup @label={{t "common.consul.service-name"}}>
|
||||
<Option @value="Name:asc" @selected={{eq "Name:asc" @sort.value}}>{{t "common.sort.alpha.asc"}}</Option>
|
||||
<Option @value="Name:desc" @selected={{eq "Name:desc" @sort.value}}>{{t "common.sort.alpha.desc"}}</Option>
|
||||
</Optgroup>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</search.Select>
|
||||
</:sort>
|
||||
</SearchBar>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { computed, action } from '@ember/object';
|
||||
import { computed, get, action } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { sort } from '@ember/object/computed';
|
||||
|
@ -32,18 +32,19 @@ export default class DataCollectionComponent extends Component {
|
|||
return this.term || this.args.search || '';
|
||||
}
|
||||
|
||||
@computed('type', 'searchMethod', 'filtered', 'searchProperties')
|
||||
@computed('type', 'searchMethod', 'filtered', 'args.filters')
|
||||
get searchable() {
|
||||
const searchproperties =
|
||||
get(this, 'args.filters.searchproperty.value') || get(this, 'args.filters.searchproperty');
|
||||
const Searchable =
|
||||
typeof this.searchMethod === 'string'
|
||||
? this.searchableMap[this.searchMethod]
|
||||
: this.args.searchable;
|
||||
|
||||
return new Searchable(this.filtered, {
|
||||
finders: Object.fromEntries(
|
||||
Object.entries(this.searchService.predicate(this.type)).filter(([key, value]) => {
|
||||
return typeof this.searchProperties === 'undefined'
|
||||
? true
|
||||
: this.searchProperties.includes(key);
|
||||
return typeof searchproperties === 'undefined' ? true : searchproperties.includes(key);
|
||||
})
|
||||
),
|
||||
});
|
||||
|
@ -89,7 +90,13 @@ export default class DataCollectionComponent extends Component {
|
|||
if (typeof predicate === 'undefined') {
|
||||
return this.content.slice();
|
||||
}
|
||||
return this.content.filter(predicate(this.args.filters));
|
||||
const filters = Object.entries(this.args.filters)
|
||||
.filter(([key, value]) => Boolean(value))
|
||||
.map(([key, value]) => {
|
||||
const val = typeof value !== 'string' ? value.value : value;
|
||||
return [key, val];
|
||||
});
|
||||
return this.content.filter(predicate(Object.fromEntries(filters)));
|
||||
}
|
||||
|
||||
@computed('args.{items.[],items.content.[]}')
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
(component 'popover-select/optgroup' components=components)
|
||||
(component 'popover-select/option'
|
||||
select=this components=components
|
||||
onclick=(queue
|
||||
onclick=(pipe
|
||||
(action "click")
|
||||
(if multiple (noop) menu.toggle)
|
||||
)
|
||||
|
|
|
@ -6,47 +6,50 @@ export default Component.extend(Slotted, {
|
|||
tagName: '',
|
||||
dom: service('dom'),
|
||||
multiple: false,
|
||||
subtractive: false,
|
||||
required: false,
|
||||
onchange: function() {},
|
||||
addOption: function(option) {
|
||||
if (typeof this._options === 'undefined') {
|
||||
this._options = new Set();
|
||||
}
|
||||
if (this.subtractive) {
|
||||
if (!option.selected) {
|
||||
this._options.add(option.value);
|
||||
}
|
||||
} else {
|
||||
if (option.selected) {
|
||||
this._options.add(option.value);
|
||||
}
|
||||
}
|
||||
this._options.add(option);
|
||||
},
|
||||
removeOption: function(option) {
|
||||
this._options.delete(option.value);
|
||||
this._options.delete(option);
|
||||
},
|
||||
actions: {
|
||||
click: function(e, value) {
|
||||
let options = [value];
|
||||
if (this.multiple) {
|
||||
if (this._options.has(value)) {
|
||||
this._options.delete(value);
|
||||
} else {
|
||||
this._options.add(value);
|
||||
click: function(option, e) {
|
||||
// required={{true}} ?
|
||||
if (!this.multiple) {
|
||||
if (option.selected && this.required) {
|
||||
return e;
|
||||
}
|
||||
[...this._options]
|
||||
.filter(item => item !== option)
|
||||
.forEach(item => {
|
||||
item.selected = false;
|
||||
});
|
||||
} else {
|
||||
if (option.selected && this.required) {
|
||||
const other = [...this._options].find(item => item !== option && item.selected);
|
||||
if (!other) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
options = this._options;
|
||||
}
|
||||
option.selected = !option.selected;
|
||||
this.onchange(
|
||||
this.dom.setEventTargetProperties(e, {
|
||||
selected: target => value,
|
||||
selected: target => option.args.value,
|
||||
selectedItems: target => {
|
||||
return [...options].join(',');
|
||||
return [...this._options]
|
||||
.filter(item => item.selected)
|
||||
.map(item => item.args.value)
|
||||
.join(',');
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
change: function(option, e) {
|
||||
this.onchange(this.dom.setEventTargetProperty(e, 'selected', selected => option));
|
||||
return e;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{#let components.MenuSeparator as |MenuSeparator|}}
|
||||
{{#let @components.MenuSeparator as |MenuSeparator|}}
|
||||
<MenuSeparator>
|
||||
<BlockSlot @name="label">
|
||||
{{label}}
|
||||
{{@label}}
|
||||
</BlockSlot>
|
||||
</MenuSeparator>
|
||||
{{yield}}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
});
|
|
@ -1,9 +1,13 @@
|
|||
{{#let components.MenuItem as |MenuItem|}}
|
||||
{{#let @components.MenuItem as |MenuItem|}}
|
||||
<MenuItem
|
||||
class={{if selected 'is-active'}}
|
||||
class={{if this.selected 'is-active'}}
|
||||
{{did-insert this.connect}}
|
||||
{{did-insert (set this "selected" @selected)}}
|
||||
{{did-update (set this "selected" @selected)}}
|
||||
{{will-destroy this.disconnect}}
|
||||
...attributes
|
||||
@onclick={{action 'click'}}
|
||||
@selected={{selected}}
|
||||
@onclick={{action @onclick this}}
|
||||
@selected={{this.selected}}
|
||||
>
|
||||
<BlockSlot @name="label">
|
||||
{{yield}}
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
dom: service('dom'),
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
this.select.addOption(this);
|
||||
},
|
||||
willDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
this.select.removeOption(this);
|
||||
},
|
||||
actions: {
|
||||
click: function(e) {
|
||||
this.onclick(e, this.value);
|
||||
},
|
||||
},
|
||||
});
|
||||
export default class Option extends Component {
|
||||
@tracked selected;
|
||||
|
||||
@action
|
||||
connect() {
|
||||
this.args.select.addOption(this);
|
||||
}
|
||||
@action
|
||||
disconnect() {
|
||||
this.args.select.removeOption(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
## SearchBar
|
||||
|
||||
```handlebars
|
||||
<SearchBar
|
||||
@value={{"search term"}}
|
||||
@onsearch={{action "search"}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `value` | `String` | | The string `value` of the freetext search bar |
|
||||
| `onsearch` | `Function` | | The action to fire when the freetext search bar changes. Emits a native event with a `target.value` property containing the text typed into the search bar |
|
||||
| `options` | `Array` | | An array of Key/Values pairs to use for options for either a filter interface or a sort interface |
|
||||
| `selected` | `Object` | | An object containing a Key/Value pair of the currently selected option |
|
||||
| `onchange` | `Function` | | The action to fire when the filter/sort changes. Emits an Event-like object, when filtering this has a `target.value` property containg the key of the selected filter, when sorting this has a `target.selected` property containing the selected Key/Value pair |
|
||||
| `secondary` | `string` | | String identifier to signify what type of secondary filter to show. Currently only value here is 'sort' |
|
||||
|
||||
`SearchBar` is used for a variety of searching behaviours, freetext searching, filtering and sorting. It is also slot based to enable you to completely overwrite the secondary search if need be.
|
||||
|
||||
### Examples
|
||||
|
||||
```handlebars
|
||||
{{! Freetext only search bar}}
|
||||
<SearchBar
|
||||
@value={{"search term"}}
|
||||
@onsearch={{action "search"}}
|
||||
/>
|
||||
```
|
||||
|
||||
```handlebars
|
||||
{{! Freetext and filter search bar}}
|
||||
<SearchBar
|
||||
@value={{search}}
|
||||
@onsearch={{action (mut search) value='target.value'}}
|
||||
@selected={{filter.selected}}
|
||||
@options={{filter.items}}
|
||||
@onchange={{action (mut filterBy) value='target.value'}}
|
||||
/>
|
||||
```
|
||||
|
||||
```handlebars
|
||||
{{! Freetext and sort search bar}}
|
||||
<SearchBar
|
||||
@value={{search}}
|
||||
@onsearch={{action (mut search) value='target.value'}}
|
||||
@secondary="sort"
|
||||
@selected={{sort.selected}}
|
||||
@options={{sort.items}}
|
||||
@onchange={{action (mut sortBy) value='target.selected.key'}}
|
||||
/>
|
||||
```
|
||||
|
||||
### See
|
||||
|
||||
- [Component Source Code](./index.js)
|
||||
- [Template Source Code](./index.hbs)
|
||||
|
||||
---
|
|
@ -1,31 +1,68 @@
|
|||
{{yield}}
|
||||
<form class={{concat 'filter-bar' (if (eq secondary 'sort') ' with-sort')}} ...attributes>
|
||||
{{#yield-slot name="primary"}}
|
||||
<fieldset>
|
||||
{{yield}}
|
||||
</fieldset>
|
||||
{{else}}
|
||||
<FreetextFilter
|
||||
@onsearch={{action onsearch}}
|
||||
@value={{value}}
|
||||
@placeholder={{or placeholder 'Search'}}
|
||||
/>
|
||||
{{/yield-slot}}
|
||||
{{#yield-slot name="secondary"}}
|
||||
<fieldset>
|
||||
{{yield}}
|
||||
</fieldset>
|
||||
{{else}}
|
||||
{{#if options}}
|
||||
{{#if (eq secondary 'sort')}}
|
||||
{{else}}
|
||||
<RadioGroup
|
||||
@keyboardAccess={{true}}
|
||||
@value={{selected.key}}
|
||||
@items={{options}}
|
||||
@onchange={{action onchange}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/yield-slot}}
|
||||
</form>
|
||||
<div
|
||||
class="search-bar"
|
||||
...attributes
|
||||
>
|
||||
<form
|
||||
class="filter-bar"
|
||||
>
|
||||
<div class="search">
|
||||
{{yield (hash
|
||||
Search=(component "freetext-filter")
|
||||
Select=(component "popover-select")
|
||||
) to="search"}}
|
||||
</div>
|
||||
<div class="filters">
|
||||
{{yield (hash
|
||||
Search=(component "freetext-filter")
|
||||
Select=(component "popover-select")
|
||||
) to="filter"}}
|
||||
</div>
|
||||
<div class="sort">
|
||||
{{yield (hash
|
||||
Search=(component "freetext-filter")
|
||||
Select=(component "popover-select")
|
||||
) to="sort"}}
|
||||
</div>
|
||||
</form>
|
||||
{{#if this.isFiltered}}
|
||||
<div class="search-bar-status">
|
||||
<dl>
|
||||
<dt>{{string-trim
|
||||
(t "component.search-bar.header"
|
||||
default="common.ui.filtered-by"
|
||||
item=""
|
||||
)
|
||||
}}</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
{{#each this.filters as |filter|}}
|
||||
{{yield (hash
|
||||
RemoveFilter=(component "search-bar/remove-filter" onclick=(action
|
||||
(get (get @filter filter.key) "change")
|
||||
(hash
|
||||
target=(hash
|
||||
selectedItems=(join filter.selected ',')
|
||||
)
|
||||
))
|
||||
)
|
||||
status=(hash
|
||||
key=filter.key
|
||||
value=(lowercase filter.value)
|
||||
)
|
||||
)
|
||||
to="status"
|
||||
}}
|
||||
{{/each}}
|
||||
<li class="remove-all">
|
||||
<Action
|
||||
{{on "click" this.removeAllFilters}}
|
||||
>
|
||||
Remove filters
|
||||
</Action>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,34 @@
|
|||
import Component from '@ember/component';
|
||||
import Slotted from 'block-slots';
|
||||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
import { diff, filters } from './utils';
|
||||
|
||||
export default Component.extend(Slotted, {
|
||||
tagName: '',
|
||||
});
|
||||
export default class SearchBar extends Component {
|
||||
// only show the filter status bar if we have searchproperty filters or
|
||||
// normal types of filters, and we are currently filtering by either of those
|
||||
get isFiltered() {
|
||||
const searchproperty = this.args.filter.searchproperty || { default: [], value: [] };
|
||||
return (
|
||||
diff(searchproperty.default, searchproperty.value).length > 0 ||
|
||||
Object.entries(this.args.filter).some(([key, value]) => {
|
||||
return key !== 'searchproperty' && typeof value.value !== 'undefined';
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// convert the object based filters to an array of iterable filters ready for
|
||||
// rendering
|
||||
get filters() {
|
||||
return filters(this.args.filter);
|
||||
}
|
||||
|
||||
@action
|
||||
removeAllFilters() {
|
||||
Object.values(this.args.filter).forEach((value, i) => {
|
||||
// put in a little queue to ensure query params are unset properly
|
||||
// ideally this would be done outside of the component
|
||||
// TODO: Look to see if this can be moved to serializeQueryParam
|
||||
// so we we aren't polluting components with queryParam related things
|
||||
setTimeout(() => value.change(value.default || []), 1 * i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
.search-bar {
|
||||
&-status {
|
||||
& {
|
||||
border-bottom: $decor-border-100;
|
||||
border-bottom-color: $gray-200;
|
||||
}
|
||||
.remove-all button {
|
||||
@extend %anchor;
|
||||
}
|
||||
li:not(.remove-all) {
|
||||
& {
|
||||
@extend %pill-200;
|
||||
border: $decor-border-100;
|
||||
border-color: $gray-200;
|
||||
color: $gray-600;
|
||||
}
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
button::before {
|
||||
@extend %with-cancel-plain-mask, %as-pseudo;
|
||||
color: $gray-600;
|
||||
margin-top: 1px;
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
}
|
||||
& {
|
||||
padding: .5rem 0;
|
||||
padding-left: .5rem;
|
||||
}
|
||||
dt::after {
|
||||
content: ':';
|
||||
padding-right: 0.3rem;
|
||||
}
|
||||
& > dl > dt {
|
||||
float: left;
|
||||
}
|
||||
dt {
|
||||
white-space: nowrap;
|
||||
}
|
||||
li {
|
||||
display: inline-flex;
|
||||
}
|
||||
li:not(:last-child) {
|
||||
margin-right: 0.3rem;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
li:not(.remove-all) {
|
||||
& {
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
dl {
|
||||
display: flex;
|
||||
}
|
||||
button {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
export default (search, secondary = () => {}) => scope => {
|
||||
return {
|
||||
scope: scope,
|
||||
...search(),
|
||||
...secondary(),
|
||||
};
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
<li>
|
||||
<Action
|
||||
...attributes
|
||||
{{on 'click' @onclick}}
|
||||
/>
|
||||
{{yield}}
|
||||
</li>
|
|
@ -0,0 +1,38 @@
|
|||
export const diff = (a, b) => {
|
||||
return a.filter(item => !b.includes(item));
|
||||
};
|
||||
/**
|
||||
* filters accepts the args.filter @attribute which is shaped like
|
||||
* {filterName: {default: ['Node', 'Address'], value: ['Address']}, ...}
|
||||
* It will turn this into an array of 'filters' shaped like
|
||||
* [{key: 'filterName', value: 'Address', selected: ["Node"]}]
|
||||
* importantly 'selected' isn't what is currently 'selected' it is what selected
|
||||
* will be once you remove this filter
|
||||
* There is more explanation in the unit tests for this function so thats worthwhile
|
||||
* checking if you are in amongst this
|
||||
*/
|
||||
export const filters = filters => {
|
||||
return Object.entries(filters)
|
||||
.filter(([key, value]) => {
|
||||
if (key === 'searchproperty') {
|
||||
return diff(value.default, value.value).length > 0;
|
||||
}
|
||||
return (value.value || []).length > 0;
|
||||
})
|
||||
.reduce((prev, [key, value]) => {
|
||||
return prev.concat(
|
||||
value.value.map(item => {
|
||||
const obj = {
|
||||
key: key,
|
||||
value: item,
|
||||
};
|
||||
if (key !== 'searchproperty') {
|
||||
obj.selected = diff(value.value, [item]);
|
||||
} else {
|
||||
obj.selected = value.value.length === 1 ? value.default : diff(value.value, [item]);
|
||||
}
|
||||
return obj;
|
||||
})
|
||||
);
|
||||
}, []);
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
kinds: {
|
||||
kind: {
|
||||
management: (item, value) => item.Type === value,
|
||||
client: (item, value) => item.Type === value,
|
||||
},
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
export default {
|
||||
statuses: {
|
||||
status: {
|
||||
passing: (item, value) => item.Status === value,
|
||||
warning: (item, value) => item.Status === value,
|
||||
critical: (item, value) => item.Status === value,
|
||||
},
|
||||
kinds: {
|
||||
kind: {
|
||||
service: (item, value) => item.Kind === value,
|
||||
node: (item, value) => item.Kind === value,
|
||||
},
|
||||
checks: {
|
||||
check: {
|
||||
serf: (item, value) => item.Type === '',
|
||||
script: (item, value) => item.Type === value,
|
||||
http: (item, value) => item.Type === value,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
accesses: {
|
||||
access: {
|
||||
allow: (item, value) => item.Action === value,
|
||||
deny: (item, value) => item.Action === value,
|
||||
'app-aware': (item, value) => typeof item.Action === 'undefined',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
kinds: {
|
||||
kind: {
|
||||
folder: (item, value) => item.isFolder,
|
||||
key: (item, value) => !item.isFolder,
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
statuses: {
|
||||
status: {
|
||||
passing: (item, value) => item.Status === value,
|
||||
warning: (item, value) => item.Status === value,
|
||||
critical: (item, value) => item.Status === value,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import setHelpers from 'mnemonist/set';
|
||||
|
||||
export default {
|
||||
kinds: {
|
||||
kind: {
|
||||
'global-management': (item, value) => item.isGlobalManagement,
|
||||
standard: (item, value) => !item.isGlobalManagement,
|
||||
},
|
||||
dcs: (item, values) => {
|
||||
datacenter: (item, values) => {
|
||||
return (
|
||||
typeof item.Datacenters === 'undefined' ||
|
||||
setHelpers.intersectionSize(values, new Set(item.Datacenters)) > 0
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import setHelpers from 'mnemonist/set';
|
||||
|
||||
export default {
|
||||
statuses: {
|
||||
status: {
|
||||
passing: (item, value) => item.Status === value,
|
||||
warning: (item, value) => item.Status === value,
|
||||
critical: (item, value) => item.Status === value,
|
||||
empty: (item, value) => item.MeshChecks.length === 0,
|
||||
},
|
||||
sources: (item, values) => {
|
||||
source: (item, values) => {
|
||||
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import setHelpers from 'mnemonist/set';
|
||||
|
||||
export default {
|
||||
kinds: {
|
||||
kind: {
|
||||
'ingress-gateway': (item, value) => item.Kind === value,
|
||||
'terminating-gateway': (item, value) => item.Kind === value,
|
||||
'mesh-gateway': (item, value) => item.Kind === value,
|
||||
|
@ -9,16 +9,17 @@ export default {
|
|||
'in-mesh': (item, value) => item.InMesh,
|
||||
'not-in-mesh': (item, value) => !item.InMesh,
|
||||
},
|
||||
statuses: {
|
||||
status: {
|
||||
passing: (item, value) => item.MeshStatus === value,
|
||||
warning: (item, value) => item.MeshStatus === value,
|
||||
critical: (item, value) => item.MeshStatus === value,
|
||||
empty: (item, value) => item.MeshChecksTotal === 0,
|
||||
},
|
||||
instances: {
|
||||
instance: {
|
||||
registered: (item, value) => item.InstanceCount > 0,
|
||||
'not-registered': (item, value) => item.InstanceCount === 0,
|
||||
},
|
||||
sources: (item, values) => {
|
||||
source: (item, values) => {
|
||||
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
kinds: {
|
||||
kind: {
|
||||
'global-management': (item, value) => item.isGlobalManagement,
|
||||
global: (item, value) => !item.Local,
|
||||
local: (item, value) => item.Local,
|
||||
|
|
|
@ -17,7 +17,9 @@ export default class Role extends Model {
|
|||
@attr('number') SyncTime;
|
||||
@attr('number') CreateIndex;
|
||||
@attr('number') ModifyIndex;
|
||||
// frontend only for ordering where CreateIndex can't be used
|
||||
// frontend only for ordering where CreateIndex can't be used i.e. for when
|
||||
// we need to order items that aren't yet saved to the backend, for example
|
||||
// in the role-selector
|
||||
@attr('number') CreateTime;
|
||||
// TODO: Figure out whether we need this or not
|
||||
@attr() Datacenters; // string[]
|
||||
|
|
|
@ -48,6 +48,16 @@ export default class Service extends Model {
|
|||
|
||||
@attr() meta; // {}
|
||||
|
||||
@computed('ChecksPassing', 'ChecksWarning', 'ChecksCritical')
|
||||
get ChecksTotal() {
|
||||
return this.ChecksPassing + this.ChecksWarning + this.ChecksCritical;
|
||||
}
|
||||
|
||||
@computed('MeshChecksPassing', 'MeshChecksWarning', 'MeshChecksCritical')
|
||||
get MeshChecksTotal() {
|
||||
return this.MeshChecksPassing + this.MeshChecksWarning + this.MeshChecksCritical;
|
||||
}
|
||||
|
||||
/* Mesh properties involve both the service and the associated proxy */
|
||||
@computed('ConnectedWithProxy', 'ConnectedWithGateway')
|
||||
get MeshEnabled() {
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import Route from 'consul-ui/routing/route';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import WithAclActions from 'consul-ui/mixins/acl/with-actions';
|
||||
|
||||
export default class IndexRoute extends Route.extend(WithAclActions) {
|
||||
@service('repository/acl') repo;
|
||||
|
||||
@service('settings') settings;
|
||||
|
||||
queryParams = {
|
||||
|
@ -19,24 +17,25 @@ export default class IndexRoute extends Route.extend(WithAclActions) {
|
|||
},
|
||||
};
|
||||
|
||||
beforeModel(transition) {
|
||||
return this.settings.findBySlug('token').then(token => {
|
||||
// If you don't have a token set or you have a
|
||||
// token set with AccessorID set to not null (new ACL mode)
|
||||
// then rewrite to the new acls
|
||||
if (!token || get(token, 'AccessorID') !== null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls.tokens');
|
||||
}
|
||||
});
|
||||
async beforeModel(transition) {
|
||||
const token = await this.settings.findBySlug('token');
|
||||
// If you don't have a token set or you have a
|
||||
// token set with AccessorID set to not null (new ACL mode)
|
||||
// then rewrite to the new acls
|
||||
if (!token || get(token, 'AccessorID') !== null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls.tokens');
|
||||
}
|
||||
}
|
||||
|
||||
model(params) {
|
||||
return hash({
|
||||
items: this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
token: this.settings.findBySlug('token'),
|
||||
});
|
||||
async model(params) {
|
||||
const _items = this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name);
|
||||
const _token = this.settings.findBySlug('token');
|
||||
return {
|
||||
items: await _items,
|
||||
token: await _token,
|
||||
};
|
||||
}
|
||||
|
||||
setupController(controller, model) {
|
||||
|
|
|
@ -9,7 +9,9 @@ export default class IndexRoute extends Route.extend(WithPolicyActions) {
|
|||
|
||||
queryParams = {
|
||||
sortBy: 'sort',
|
||||
dc: 'dc',
|
||||
datacenter: {
|
||||
as: 'dc',
|
||||
},
|
||||
kind: 'kind',
|
||||
searchproperty: {
|
||||
as: 'searchproperty',
|
||||
|
@ -29,6 +31,7 @@ export default class IndexRoute extends Route.extend(WithPolicyActions) {
|
|||
this.modelFor('nspace').nspace.substr(1)
|
||||
),
|
||||
}),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ export default class IndexRoute extends Route.extend(WithRoleActions) {
|
|||
this.modelFor('nspace').nspace.substr(1)
|
||||
),
|
||||
}),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -21,16 +21,15 @@ export default class IndexRoute extends Route.extend(WithTokenActions) {
|
|||
},
|
||||
};
|
||||
|
||||
beforeModel(transition) {
|
||||
return this.settings.findBySlug('token').then(token => {
|
||||
// If you have a token set with AccessorID set to null (legacy mode)
|
||||
// then rewrite to the old acls
|
||||
if (token && get(token, 'AccessorID') === null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls');
|
||||
}
|
||||
});
|
||||
async beforeModel(transition) {
|
||||
const token = await this.settings.findBySlug('token');
|
||||
// If you have a token set with AccessorID set to null (legacy mode)
|
||||
// then rewrite to the old acls
|
||||
if (token && get(token, 'AccessorID') === null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls');
|
||||
}
|
||||
}
|
||||
|
||||
model(params) {
|
||||
|
@ -43,6 +42,7 @@ export default class IndexRoute extends Route.extend(WithTokenActions) {
|
|||
}),
|
||||
nspace: this.modelFor('nspace').nspace.substr(1),
|
||||
token: this.settings.findBySlug('token'),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,11 @@ export default class IndexRoute extends Route {
|
|||
},
|
||||
};
|
||||
|
||||
model(params) {
|
||||
async model(params) {
|
||||
return {
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
nspace: this.modelFor('nspace').nspace.substr(1),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import Route from 'consul-ui/routing/route';
|
||||
import { hash } from 'rsvp';
|
||||
|
||||
export default class IndexRoute extends Route {
|
||||
@service('data-source/service') data;
|
||||
|
@ -18,13 +17,16 @@ export default class IndexRoute extends Route {
|
|||
},
|
||||
};
|
||||
|
||||
model(params) {
|
||||
async model(params) {
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
const nspace = this.modelFor('nspace').nspace.substr(1);
|
||||
return hash({
|
||||
items: this.data.source(uri => uri`/${nspace}/${dc}/nodes`),
|
||||
leader: this.data.source(uri => uri`/${nspace}/${dc}/leader`),
|
||||
});
|
||||
const items = this.data.source(uri => uri`/${nspace}/${dc}/nodes`);
|
||||
const leader = this.data.source(uri => uri`/${nspace}/${dc}/leader`);
|
||||
return {
|
||||
items: await items,
|
||||
leader: await leader,
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
};
|
||||
}
|
||||
|
||||
setupController(controller, model) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import Route from 'consul-ui/routing/route';
|
||||
import { hash } from 'rsvp';
|
||||
|
||||
import WithNspaceActions from 'consul-ui/mixins/nspace/with-actions';
|
||||
export default class IndexRoute extends Route.extend(WithNspaceActions) {
|
||||
|
@ -19,10 +18,11 @@ export default class IndexRoute extends Route.extend(WithNspaceActions) {
|
|||
},
|
||||
};
|
||||
|
||||
model(params) {
|
||||
return hash({
|
||||
items: this.data.source(uri => uri`/*/*/namespaces`),
|
||||
});
|
||||
async model(params) {
|
||||
return {
|
||||
items: await this.data.source(uri => uri`/*/*/namespaces`),
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
};
|
||||
}
|
||||
|
||||
setupController(controller, model) {
|
||||
|
|
|
@ -27,6 +27,7 @@ export default class IndexRoute extends Route {
|
|||
dc,
|
||||
nspace,
|
||||
items,
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ export default class HealthchecksRoute extends Route {
|
|||
queryParams = {
|
||||
sortBy: 'sort',
|
||||
status: 'status',
|
||||
kind: 'kind',
|
||||
check: 'check',
|
||||
searchproperty: {
|
||||
as: 'searchproperty',
|
||||
|
|
|
@ -14,11 +14,12 @@ export default class IndexRoute extends Route {
|
|||
},
|
||||
};
|
||||
|
||||
model(params) {
|
||||
async model(params) {
|
||||
return {
|
||||
dc: this.modelFor('dc').dc.Name,
|
||||
nspace: this.modelFor('nspace').nspace.substr(1) || 'default',
|
||||
slug: this.paramsFor('dc.services.show').name,
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,12 @@ export default class ServicesRoute extends Route {
|
|||
.slice(0, -1)
|
||||
.join('.');
|
||||
const name = this.modelFor(parent).slug;
|
||||
const gatewayServices = await this.data.source(
|
||||
uri => uri`/${nspace}/${dc}/gateways/for-service/${name}`
|
||||
);
|
||||
const items = await this.data.source(uri => uri`/${nspace}/${dc}/gateways/for-service/${name}`);
|
||||
return {
|
||||
dc,
|
||||
nspace,
|
||||
gatewayServices,
|
||||
items,
|
||||
searchProperties: this.queryParams.searchproperty.empty[0],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
@import 'consul-ui/components/freetext-filter';
|
||||
@import 'consul-ui/components/informed-action';
|
||||
@import 'consul-ui/components/tab-nav';
|
||||
@import 'consul-ui/components/search-bar';
|
||||
|
||||
@import 'consul-ui/components/consul/tomography/graph';
|
||||
@import 'consul-ui/components/consul/discovery-chain';
|
||||
|
|
|
@ -18,7 +18,7 @@ html[data-route$='edit'] .app-view > header + div > *:first-child {
|
|||
/* if it is a filter bar and the thing after the filter bar is a p then it also */
|
||||
/* needs a top margun :S */
|
||||
%app-view-content .tab-section > *:first-child:not(.filter-bar):not(table),
|
||||
%app-view-content .tab-section > .filter-bar + p,
|
||||
%app-view-content .tab-section > .search-bar + p,
|
||||
%app-view-content .tab-section .consul-health-check-list {
|
||||
margin-top: 1.25em;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ h3 {
|
|||
%radio-card header,
|
||||
fieldset > header,
|
||||
%main-nav-horizontal-action,
|
||||
%app-view-content div > dl > dt,
|
||||
%definition-table dt,
|
||||
%table caption,
|
||||
%tbody-th,
|
||||
%form-element > span {
|
||||
|
|
|
@ -1,83 +1,93 @@
|
|||
{{page-title 'ACLs'}}
|
||||
{{#let (hash
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Name:asc") as |sort|}}
|
||||
<AppView>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Acl::Notifications
|
||||
@status={{status}}
|
||||
@type={{type}}
|
||||
@error={{error}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
ACL Tokens <em>{{format-number items.length}} total</em>
|
||||
</h1>
|
||||
<label for="toolbar-toggle"></label>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.acls.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Acl::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
{{#let
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
(hash
|
||||
value=(or sortBy "Name:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
}}
|
||||
(hash
|
||||
kind=(hash
|
||||
value=(if kind (split kind ',') undefined)
|
||||
change=(action (mut kind) value="target.selectedItems")
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
|
||||
<AppView>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Acl::Notifications
|
||||
@status={{status}}
|
||||
@type={{type}}
|
||||
@error={{error}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="acl"
|
||||
@sort={{sort}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Acl::List
|
||||
@items={{collection.items}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
ACL Tokens <em>{{format-number items.length}} total</em>
|
||||
</h1>
|
||||
<label for="toolbar-toggle"></label>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.acls.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Acl::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
|
||||
@filter={{filters}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="acl"
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Acl::List
|
||||
@items={{collection.items}}
|
||||
|
||||
@ondelete={{route-action 'delete'}}
|
||||
@onuse={{route-action 'use'}}
|
||||
@onclone={{route-action 'clone'}}
|
||||
>
|
||||
</Consul::Acl::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No ACLs found
|
||||
{{else}}
|
||||
Welcome to ACLs
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No ACLs where found matching that search, or you may not have access to view the ACLs you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any ACLs yet, or you may not have access to view ACLs yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
|
||||
@ondelete={{route-action 'delete'}}
|
||||
@onuse={{route-action 'use'}}
|
||||
@onclone={{route-action 'clone'}}
|
||||
>
|
||||
</Consul::Acl::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No ACLs found
|
||||
{{else}}
|
||||
Welcome to ACLs
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No ACLs where found matching that search, or you may not have access to view the ACLs you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any ACLs yet, or you may not have access to view ACLs yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
|
|
|
@ -3,104 +3,118 @@
|
|||
{{else}}
|
||||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
{{#let (hash
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
dcs=(if dc (split dc ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Name' 'Description')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Name:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Name:asc") as |sort|}}
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Policy::Notifications
|
||||
@type={{type}}
|
||||
@status={{status}}
|
||||
@item={{item}}
|
||||
@error={{error}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Access Controls
|
||||
</h1>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="nav">
|
||||
{{#if isAuthorized }}
|
||||
{{partial 'dc/acls/nav'}}
|
||||
|
||||
(hash
|
||||
kind=(hash
|
||||
value=(if kind (split kind ',') undefined)
|
||||
change=(action (mut kind) value="target.selectedItems")
|
||||
)
|
||||
datacenter=(hash
|
||||
value=(if datacenter (split datacenter ',') undefined)
|
||||
change=(action (mut datacenter) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Policy::Notifications
|
||||
@type={{type}}
|
||||
@status={{status}}
|
||||
@item={{item}}
|
||||
@error={{error}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Access Controls
|
||||
</h1>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="nav">
|
||||
{{#if isAuthorized }}
|
||||
{{partial 'dc/acls/nav'}}
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.acls.policies.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Policy::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
|
||||
@filter={{filters}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.acls.policies.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Policy::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="policy"
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Policy::List
|
||||
@items={{collection.items}}
|
||||
@ondelete={{route-action 'delete'}}
|
||||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No policies found
|
||||
{{else}}
|
||||
Welcome to Policies
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No policies where found matching that search, or you may not have access to view the policies you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any policies, or you may not have access to view policies yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<li class="docs-link">
|
||||
<a href="{{env 'CONSUL_DOCS_URL'}}/commands/acl/policy" rel="noopener noreferrer" target="_blank">Documentation on policies</a>
|
||||
</li>
|
||||
<li class="learn-link">
|
||||
<a href="{{env 'CONSUL_LEARN_URL'}}/consul/security-networking/managing-acl-policies" rel="noopener noreferrer" target="_blank">Read the guide</a>
|
||||
</li>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
dc=(action (mut dc) value="target.selectedItems")
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="role"
|
||||
@sort={{sort}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Policy::List
|
||||
@items={{collection.items}}
|
||||
@ondelete={{route-action 'delete'}}
|
||||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No policies found
|
||||
{{else}}
|
||||
Welcome to Policies
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No policies where found matching that search, or you may not have access to view the policies you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any policies, or you may not have access to view policies yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<li class="docs-link">
|
||||
<a href="{{env 'CONSUL_DOCS_URL'}}/commands/acl/policy" rel="noopener noreferrer" target="_blank">Documentation on policies</a>
|
||||
</li>
|
||||
<li class="learn-link">
|
||||
<a href="{{env 'CONSUL_LEARN_URL'}}/consul/security-networking/managing-acl-policies" rel="noopener noreferrer" target="_blank">Read the guide</a>
|
||||
</li>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -4,13 +4,28 @@
|
|||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
|
||||
{{#let (hash
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Name' 'Description' 'Policy')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Name:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Name:asc") as |sort|}}
|
||||
|
||||
(hash
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
|
@ -43,19 +58,15 @@
|
|||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="role"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
@ -99,5 +110,4 @@
|
|||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -4,110 +4,122 @@
|
|||
{{page-title 'Access Controls'}}
|
||||
{{/if}}
|
||||
|
||||
{{#let (hash
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Description' 'Policy' 'Role')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "CreateTime:desc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "CreateTime:desc") as |sort|}}
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Token::Notifications
|
||||
@type={{type}}
|
||||
@status={{status}}
|
||||
@item={{item}}
|
||||
@error={{error}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Access Controls
|
||||
</h1>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="nav">
|
||||
{{#if isAuthorized }}
|
||||
{{partial 'dc/acls/nav'}}
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.acls.tokens.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
{{#if (gt items.length 0)}}
|
||||
<Consul::Token::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
(hash
|
||||
kind=(hash
|
||||
value=(if kind (split kind ',') undefined)
|
||||
change=(action (mut kind) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
{{#if (token/is-legacy items)}}
|
||||
<Notice
|
||||
@type="info"
|
||||
as |notice|>
|
||||
<notice.Header>
|
||||
<h2>Update</h2>
|
||||
</notice.Header>
|
||||
<notice.Body>
|
||||
<p data-test-notification-update>We have upgraded our ACL System to allow the creation of reusable policies that can be applied to tokens. Read more about the changes and how to upgrade legacy tokens in our <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl-migrate-tokens.html" target="_blank" rel="noopener noreferrer">documentation</a>.</p>
|
||||
</notice.Body>
|
||||
</Notice>
|
||||
{{/if}}
|
||||
<DataCollection
|
||||
@type="token"
|
||||
@sort={{sort}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Token::List
|
||||
@items={{collection.items}}
|
||||
@token={{token}}
|
||||
@onuse={{route-action 'use'}}
|
||||
@ondelete={{route-action 'delete'}}
|
||||
@onlogout={{route-action 'logout'}}
|
||||
@onclone={{route-action 'clone'}}
|
||||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No tokens found
|
||||
{{else}}
|
||||
Welcome to ACL Tokens
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No tokens where found matching that search, or you may not have access to view the tokens you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any tokens, or you may not have access to view tokens yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
|
||||
<AppView
|
||||
@authorized={{isAuthorized}}
|
||||
@enabled={{isEnabled}}
|
||||
>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Token::Notifications
|
||||
@type={{type}}
|
||||
@status={{status}}
|
||||
@item={{item}}
|
||||
@error={{error}}
|
||||
/>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Access Controls
|
||||
</h1>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="nav">
|
||||
{{#if isAuthorized }}
|
||||
{{partial 'dc/acls/nav'}}
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.acls.tokens.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
{{#if (gt items.length 0)}}
|
||||
<Consul::Token::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
|
||||
@filter={{filters}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
{{#if (token/is-legacy items)}}
|
||||
<Notice
|
||||
@type="info"
|
||||
as |notice|>
|
||||
<notice.Header>
|
||||
<h2>Update</h2>
|
||||
</notice.Header>
|
||||
<notice.Body>
|
||||
<p data-test-notification-update>We have upgraded our ACL System to allow the creation of reusable policies that can be applied to tokens. Read more about the changes and how to upgrade legacy tokens in our <a href="{{env 'CONSUL_DOCS_URL'}}/guides/acl-migrate-tokens.html" target="_blank" rel="noopener noreferrer">documentation</a>.</p>
|
||||
</notice.Body>
|
||||
</Notice>
|
||||
{{/if}}
|
||||
<DataCollection
|
||||
@type="token"
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Token::List
|
||||
@items={{collection.items}}
|
||||
@token={{token}}
|
||||
@onuse={{route-action 'use'}}
|
||||
@ondelete={{route-action 'delete'}}
|
||||
@onlogout={{route-action 'logout'}}
|
||||
@onclone={{route-action 'clone'}}
|
||||
/>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No tokens found
|
||||
{{else}}
|
||||
Welcome to ACL Tokens
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No tokens where found matching that search, or you may not have access to view the tokens you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any tokens, or you may not have access to view tokens yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
|
|
|
@ -6,104 +6,115 @@
|
|||
</BlockSlot>
|
||||
|
||||
<BlockSlot @name="loaded">
|
||||
{{#let api.data as |items|}}
|
||||
{{#let (hash
|
||||
accesses=(if access (split access ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'SourceName' 'DestinationName')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Action:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
|
||||
(hash
|
||||
access=(hash
|
||||
value=(if access (split access ',') undefined)
|
||||
change=(action (mut access) value="target.selectedItems")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Action:asc") as |sort|}}
|
||||
<AppView>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Intentions <em>{{format-number items.length}} total</em>
|
||||
</h1>
|
||||
<label for="toolbar-toggle"></label>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.intentions.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Intention::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
api.data
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
as |sort filters items|}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
access=(action (mut access) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
<AppView>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
Intentions <em>{{format-number items.length}} total</em>
|
||||
</h1>
|
||||
<label for="toolbar-toggle"></label>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<a data-test-create href="{{href-to 'dc.intentions.create'}}" class="type-create">Create</a>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="toolbar">
|
||||
|
||||
</BlockSlot>
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Intention::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
|
||||
@filter={{filters}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataWriter
|
||||
@sink={{concat '/' dc '/' nspace '/intention/'}}
|
||||
@type="intention"
|
||||
@ondelete={{refresh-route}}
|
||||
as |writer|>
|
||||
<BlockSlot @name="content">
|
||||
<DataWriter
|
||||
@sink={{concat '/' dc '/' nspace '/intention/'}}
|
||||
<DataCollection
|
||||
@type="intention"
|
||||
@ondelete={{refresh-route}}
|
||||
as |writer|>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="intention"
|
||||
@sort={{sort}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Intention::List
|
||||
@items={{collection.items}}
|
||||
@delete={{writer.delete}}
|
||||
as |list|>
|
||||
<list.CustomResourceNotice />
|
||||
<list.Table />
|
||||
</Consul::Intention::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No intentions found
|
||||
{{else}}
|
||||
Welcome to Intentions
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No intentions where found matching that search, or you may not have access to view the intentions you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any intentions, or you may not have access to view intentions yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<li class="docs-link">
|
||||
<a href="{{env 'CONSUL_DOCS_URL'}}/commands/intention" rel="noopener noreferrer" target="_blank">Documentation on intentions</a>
|
||||
</li>
|
||||
<li class="learn-link">
|
||||
<a href="{{env 'CONSUL_DOCS_LEARN_URL'}}/consul/getting-started/connect" rel="noopener noreferrer" target="_blank">Read the guide</a>
|
||||
</li>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</DataWriter>
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Intention::List
|
||||
@items={{collection.items}}
|
||||
@delete={{writer.delete}}
|
||||
as |list|>
|
||||
<list.CustomResourceNotice />
|
||||
<list.Table />
|
||||
</Consul::Intention::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState @allowLogin={{true}}>
|
||||
<BlockSlot @name="header">
|
||||
<h2>
|
||||
{{#if (gt items.length 0)}}
|
||||
No intentions found
|
||||
{{else}}
|
||||
Welcome to Intentions
|
||||
{{/if}}
|
||||
</h2>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
{{#if (gt items.length 0)}}
|
||||
No intentions where found matching that search, or you may not have access to view the intentions you are searching for.
|
||||
{{else}}
|
||||
There don't seem to be any intentions, or you may not have access to view intentions yet.
|
||||
{{/if}}
|
||||
</p>
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="actions">
|
||||
<li class="docs-link">
|
||||
<a href="{{env 'CONSUL_DOCS_URL'}}/commands/intention" rel="noopener noreferrer" target="_blank">Documentation on intentions</a>
|
||||
</li>
|
||||
<li class="learn-link">
|
||||
<a href="{{env 'CONSUL_DOCS_LEARN_URL'}}/consul/getting-started/connect" rel="noopener noreferrer" target="_blank">Read the guide</a>
|
||||
</li>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</DataWriter>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
|
@ -1,8 +1,21 @@
|
|||
{{page-title 'Key/Value'}}
|
||||
{{#let (hash
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Kind:asc") as |sort|}}
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Kind:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
|
||||
(hash
|
||||
kind=(hash
|
||||
value=(if kind (split kind ',') undefined)
|
||||
change=(action (mut kind) value="target.selectedItems")
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
<AppView>
|
||||
{{#if (not-eq parent.Key '/') }}
|
||||
<BlockSlot @name="breadcrumbs">
|
||||
|
@ -31,12 +44,8 @@
|
|||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
|
@ -57,7 +66,7 @@
|
|||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="kv"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
@ -104,5 +113,4 @@
|
|||
</DataWriter>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -1,14 +1,31 @@
|
|||
{{page-title 'Nodes'}}
|
||||
<EventSource @src={{items}} />
|
||||
<EventSource @src={{leader}} />
|
||||
{{#let (hash
|
||||
statuses=(if status (split status ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Node' 'Address' 'Meta')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Status:asc") as |sort|}}
|
||||
|
||||
(hash
|
||||
status=(hash
|
||||
value=(if status (split status ',') undefined)
|
||||
change=(action (mut status) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
<AppView>
|
||||
<BlockSlot @name="header">
|
||||
<h1>
|
||||
|
@ -23,20 +40,15 @@
|
|||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
status=(action (mut status) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="node"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
@ -59,5 +71,4 @@
|
|||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -1,40 +1,55 @@
|
|||
{{#let (hash
|
||||
statuses=(if status (split status ',') undefined)
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
checks=(if check (split check ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Status:asc") as |sort|}}
|
||||
|
||||
(hash
|
||||
status=(hash
|
||||
value=(if status (split status ',') undefined)
|
||||
change=(action (mut status) value="target.selectedItems")
|
||||
)
|
||||
kind=(hash
|
||||
value=(if kind (split kind ',') undefined)
|
||||
change=(action (mut kind) value="target.selectedItems")
|
||||
)
|
||||
check=(hash
|
||||
value=(if check (split check ',') undefined)
|
||||
change=(action (mut check) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
item.Checks
|
||||
|
||||
as |sort filters items|}}
|
||||
<div class="tab-section">
|
||||
{{#if (gt item.Checks.length 0) }}
|
||||
{{#if (gt items.length 0) }}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::HealthCheck::SearchBar
|
||||
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
@searchproperties={{searchProperties}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
status=(action (mut status) value="target.selectedItems")
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
check=(action (mut check) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
<DataCollection
|
||||
@type="health-check"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{item.Checks}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::HealthCheck::List
|
||||
|
@ -45,12 +60,11 @@
|
|||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
This node has no health checks{{#if (gt item.Checks.length 0)}} matching that search{{/if}}.
|
||||
This node has no health checks{{#if (gt items.length 0)}} matching that search{{/if}}.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</div>
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -1,13 +1,32 @@
|
|||
{{#let (hash
|
||||
statuses=(if status (split status ',') undefined)
|
||||
sources=(if source (split source ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Status:asc") as |sort|}}
|
||||
{{#let (reject-by 'Service.Kind' 'connect-proxy' item.Services) as |items|}}
|
||||
|
||||
(hash
|
||||
status=(hash
|
||||
value=(if status (split status ',') undefined)
|
||||
change=(action (mut status) value="target.selectedItems")
|
||||
)
|
||||
source=(hash
|
||||
value=(if source (split source ',') undefined)
|
||||
change=(action (mut source) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
(reject-by 'Service.Kind' 'connect-proxy' item.Services)
|
||||
|
||||
as |sort filters items|}}
|
||||
<div class="tab-section">
|
||||
{{#if (gt items.length 0) }}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
|
@ -18,20 +37,14 @@
|
|||
@searchproperties={{searchProperties}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
status=(action (mut status) value="target.selectedItems")
|
||||
source=(action (mut source) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{! filter out any sidecar proxies }}
|
||||
<DataCollection
|
||||
@type="service-instance"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
@ -55,6 +68,4 @@
|
|||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</div>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -1,12 +1,27 @@
|
|||
{{page-title 'Namespaces'}}
|
||||
{{#let (hash
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Name' 'Description' 'Policy' 'Role')
|
||||
<EventSource @src={{items}} />
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Name:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Name:asc") as |sort|}}
|
||||
<EventSource @src={{items}} />
|
||||
|
||||
(hash
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
|
||||
<AppView>
|
||||
<BlockSlot @name="notification" as |status type item error|>
|
||||
<Consul::Nspace::Notifications
|
||||
|
@ -30,19 +45,15 @@
|
|||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="nspace"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
@ -86,5 +97,4 @@
|
|||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</AppView>
|
||||
{{/let}}
|
||||
{{/let}}
|
|
@ -4,15 +4,31 @@
|
|||
|
||||
{{#let
|
||||
|
||||
(or sortBy "Status:asc")
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
|
||||
(hash
|
||||
statuses=(if status (split status ',') undefined)
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
sources=(if source (split source ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Name' 'Tags')
|
||||
status=(hash
|
||||
value=(if status (split status ',') undefined)
|
||||
change=(action (mut status) value="target.selectedItems")
|
||||
)
|
||||
kind=(hash
|
||||
value=(if kind (split kind ',') undefined)
|
||||
change=(action (mut kind) value="target.selectedItems")
|
||||
)
|
||||
source=(hash
|
||||
value=(if source (split source ',') undefined)
|
||||
change=(action (mut source) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -36,22 +52,16 @@ as |sort filters items|}}
|
|||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
status=(action (mut status) value="target.selectedItems")
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
source=(action (mut source) value="target.selectedItems")
|
||||
}}
|
||||
|
||||
/>
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="service"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
|
|
@ -1,41 +1,52 @@
|
|||
{{#let (hash
|
||||
statuses=(if status (split status ',') undefined)
|
||||
kinds=(if kind (split kind ',') undefined)
|
||||
checks=(if check (split check ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Status:asc") as |sort|}}
|
||||
|
||||
(hash
|
||||
status=(hash
|
||||
value=(if status (split status ',') undefined)
|
||||
change=(action (mut status) value="target.selectedItems")
|
||||
)
|
||||
check=(hash
|
||||
value=(if check (split check ',') undefined)
|
||||
change=(action (mut check) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
item.MeshChecks
|
||||
|
||||
as |sort filters items|}}
|
||||
<div class="tab-section">
|
||||
|
||||
{{#if (gt item.MeshChecks.length 0) }}
|
||||
{{#if (gt items.length 0) }}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::HealthCheck::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
@searchproperties={{searchProperties}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
status=(action (mut status) value="target.selectedItems")
|
||||
kind=(action (mut kind) value="target.selectedItems")
|
||||
check=(action (mut check) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
<DataCollection
|
||||
@type="health-check"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{item.MeshChecks}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::HealthCheck::List
|
||||
|
@ -46,7 +57,7 @@
|
|||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
This instance has no health checks{{#if (gt item.MeshChecks.length 0)}} matching that search{{/if}}.
|
||||
This instance has no health checks{{#if (gt items.length 0)}} matching that search{{/if}}.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
|
@ -54,5 +65,4 @@
|
|||
</DataCollection>
|
||||
|
||||
</div>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
<div class="tab-section">
|
||||
{{#let (hash
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "DestinationName:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "DestinationName:asc") as |sort|}}
|
||||
{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}}
|
||||
|
||||
(hash
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
proxy.Service.Proxy.Upstreams
|
||||
|
||||
as |sort filters items|}}
|
||||
{{#if (gt items.length 0)}}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::UpstreamInstance::SearchBar
|
||||
@search={{search}}
|
||||
|
@ -14,20 +28,16 @@
|
|||
@searchproperties={{searchProperties}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
<DataCollection
|
||||
@type="upstream-instance"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{proxy.Service.Proxy.Upstreams}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::UpstreamInstance::List
|
||||
|
@ -40,12 +50,11 @@
|
|||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
This service has no upstreams{{#if (gt proxy.Service.Proxy.Upstreams.length 0)}} matching that search{{/if}}.
|
||||
This service has no upstreams{{#if (gt items.length 0)}} matching that search{{/if}}.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</div>
|
|
@ -1,36 +1,49 @@
|
|||
<div class="tab-section">
|
||||
{{#let (hash
|
||||
statuses=(if status (split status ',') undefined)
|
||||
sources=(if source (split source ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Status:asc") as |sort|}}
|
||||
|
||||
(hash
|
||||
status=(hash
|
||||
value=(if status (split status ',') undefined)
|
||||
change=(action (mut status) value="target.selectedItems")
|
||||
)
|
||||
source=(hash
|
||||
value=(if source (split source ',') undefined)
|
||||
change=(action (mut source) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
{{#if (gt items.length 0) }}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::ServiceInstance::SearchBar
|
||||
@sources={{get (collection items) 'ExternalSources'}}
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
@searchproperties={{searchProperties}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
status=(action (mut status) value="target.selectedItems")
|
||||
source=(action (mut source) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{! Service > Service Instance view doesn't require filtering of proxies }}
|
||||
<DataCollection
|
||||
@type="service-instance"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
|
@ -51,6 +64,5 @@
|
|||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</div>
|
||||
|
|
|
@ -12,74 +12,83 @@ as |api|>
|
|||
<ErrorState @error={{api.error}} />
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="loaded">
|
||||
{{#let api.data as |items|}}
|
||||
{{#let (hash
|
||||
accesses=(if access (split access ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'SourceName' 'DestinationName')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Action:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
|
||||
(hash
|
||||
access=(hash
|
||||
value=(if access (split access ',') undefined)
|
||||
change=(action (mut access) value="target.selectedItems")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Action:asc") as |sort|}}
|
||||
<div class="tab-section">
|
||||
<Portal @target="app-view-actions">
|
||||
<a data-test-create href={{href-to 'dc.services.show.intentions.create'}} class="type-create">Create</a>
|
||||
</Portal>
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
api.data
|
||||
|
||||
as |sort filters items|}}
|
||||
<div class="tab-section">
|
||||
<Portal @target="app-view-actions">
|
||||
<a data-test-create href={{href-to 'dc.services.show.intentions.create'}} class="type-create">Create</a>
|
||||
</Portal>
|
||||
{{#if (gt items.length 0) }}
|
||||
<Consul::Intention::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
<Consul::Intention::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
@sort={{sort}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
access=(action (mut access) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
@filter={{filters}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
<DataWriter
|
||||
@sink={{concat '/' dc '/' nspace '/intention/'}}
|
||||
<DataWriter
|
||||
@sink={{concat '/' dc '/' nspace '/intention/'}}
|
||||
@type="intention"
|
||||
@ondelete={{refresh-route}}
|
||||
as |writer|>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="intention"
|
||||
@ondelete={{refresh-route}}
|
||||
as |writer|>
|
||||
<BlockSlot @name="content">
|
||||
<DataCollection
|
||||
@type="intention"
|
||||
@sort={{sort}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Intention::List
|
||||
@items={{collection.items}}
|
||||
@check={{search}}
|
||||
@delete={{writer.delete}}
|
||||
as |list|>
|
||||
<list.CustomResourceNotice />
|
||||
<list.CheckNotice />
|
||||
<list.Table @routeName="dc.services.show.intentions.edit" />
|
||||
</Consul::Intention::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
There are no intentions {{if (gt items.length 0) 'found '}} for this service.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</DataWriter>
|
||||
</div>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Intention::List
|
||||
@items={{collection.items}}
|
||||
@check={{search}}
|
||||
@delete={{writer.delete}}
|
||||
as |list|>
|
||||
<list.CustomResourceNotice />
|
||||
<list.CheckNotice />
|
||||
<list.Table @routeName="dc.services.show.intentions.edit" />
|
||||
</Consul::Intention::List>
|
||||
</collection.Collection>
|
||||
<collection.Empty>
|
||||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
There are no intentions {{if (gt items.length 0) 'found '}} for this service.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
</BlockSlot>
|
||||
</DataWriter>
|
||||
</div>
|
||||
{{/let}}
|
||||
</BlockSlot>
|
||||
</DataLoader>
|
||||
|
|
|
@ -1,27 +1,39 @@
|
|||
<EventSource @src={{gatewayServices}} />
|
||||
<EventSource @src={{items}} />
|
||||
<div class="tab-section">
|
||||
{{#let (hash
|
||||
instances=(if instance (split instance ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Name' 'Tags')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Name:asc") as |sort|}}
|
||||
{{#if (gt gatewayServices.length 0)}}
|
||||
|
||||
(hash
|
||||
instance=(hash
|
||||
value=(if instance (split instance ',') undefined)
|
||||
change=(action (mut instance) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
{{#if (gt items.length 0)}}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::Upstream::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
instance=(action (mut instance) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
<p>
|
||||
|
@ -30,10 +42,10 @@
|
|||
</p>
|
||||
<DataCollection
|
||||
@type="service"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{gatewayServices}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Service::List
|
||||
|
@ -46,12 +58,11 @@
|
|||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
There are no linked services{{#if (gt gatewayServices.length 0)}} matching that search{{/if}}.
|
||||
There are no linked services{{#if (gt items.length 0)}} matching that search{{/if}}.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</div>
|
||||
|
|
|
@ -1,27 +1,39 @@
|
|||
<EventSource @src={{gatewayServices}} />
|
||||
<EventSource @src={{items}} />
|
||||
<div class="tab-section">
|
||||
{{#let (hash
|
||||
instances=(if instance (split instance ',') undefined)
|
||||
searchproperties=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
(array 'Name' 'Tags')
|
||||
{{#let
|
||||
|
||||
(hash
|
||||
value=(or sortBy "Status:asc")
|
||||
change=(action (mut sortBy) value="target.selected")
|
||||
)
|
||||
) as |filters|}}
|
||||
{{#let (or sortBy "Status:asc") as |sort|}}
|
||||
{{#if (gt gatewayServices.length 0)}}
|
||||
|
||||
(hash
|
||||
instance=(hash
|
||||
value=(if instance (split instance ',') undefined)
|
||||
change=(action (mut instance) value="target.selectedItems")
|
||||
)
|
||||
searchproperty=(hash
|
||||
value=(if (not-eq searchproperty undefined)
|
||||
(split searchproperty ',')
|
||||
searchProperties
|
||||
)
|
||||
change=(action (mut searchproperty) value="target.selectedItems")
|
||||
default=searchProperties
|
||||
)
|
||||
)
|
||||
|
||||
items
|
||||
|
||||
as |sort filters items|}}
|
||||
{{#if (gt items.length 0)}}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::Upstream::SearchBar
|
||||
@search={{search}}
|
||||
@onsearch={{action (mut search) value="target.value"}}
|
||||
|
||||
@sort={{sort}}
|
||||
@onsort={{action (mut sortBy) value="target.selected"}}
|
||||
|
||||
@filter={{filters}}
|
||||
@onfilter={{hash
|
||||
searchproperty=(action (mut searchproperty) value="target.selectedItems")
|
||||
instance=(action (mut instance) value="target.selectedItems")
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
<p>
|
||||
|
@ -29,10 +41,10 @@
|
|||
</p>
|
||||
<DataCollection
|
||||
@type="service"
|
||||
@sort={{sort}}
|
||||
@sort={{sort.value}}
|
||||
@filters={{filters}}
|
||||
@search={{search}}
|
||||
@items={{gatewayServices}}
|
||||
@items={{items}}
|
||||
as |collection|>
|
||||
<collection.Collection>
|
||||
<Consul::Upstream::List
|
||||
|
@ -46,12 +58,11 @@
|
|||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
<p>
|
||||
There are no upstreams{{#if (gt gatewayServices.length 0)}} matching that search{{/if}}.
|
||||
There are no upstreams{{#if (gt items.length 0)}} matching that search{{/if}}.
|
||||
</p>
|
||||
</BlockSlot>
|
||||
</EmptyState>
|
||||
</collection.Empty>
|
||||
</DataCollection>
|
||||
{{/let}}
|
||||
{{/let}}
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// if we can't find the message, take the last part of the identifier and
|
||||
// ucfirst it so it looks human
|
||||
export default function missingMessage(key, locales) {
|
||||
const last = key
|
||||
.split('.')
|
||||
.pop()
|
||||
.replaceAll('-', ' ');
|
||||
return `${last.substr(0, 1).toUpperCase()}${last.substr(1)}`;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | search-bar', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function(assert) {
|
||||
// Set any properties with this.set('myProperty', 'value');
|
||||
this.set('search', function(e) {});
|
||||
|
||||
await render(hbs`<SearchBar @onsearch={{action search}}/>`);
|
||||
|
||||
assert.equal(this.element.textContent.trim(), 'Search');
|
||||
|
||||
// Template block usage:
|
||||
await render(hbs`
|
||||
<SearchBar @onsearch={{action search}}></SearchBar>
|
||||
`);
|
||||
|
||||
assert.equal(this.element.textContent.trim(), 'Search');
|
||||
});
|
||||
});
|
|
@ -6,7 +6,6 @@ import {
|
|||
collection,
|
||||
text,
|
||||
isPresent,
|
||||
triggerable,
|
||||
} from 'ember-cli-page-object';
|
||||
|
||||
import { alias } from 'ember-cli-page-object/macros';
|
||||
|
@ -26,9 +25,7 @@ import pageFactory from 'consul-ui/components/hashicorp-consul/pageobject';
|
|||
import radiogroup from 'consul-ui/components/radio-group/pageobject';
|
||||
import tabgroup from 'consul-ui/components/tab-nav/pageobject';
|
||||
import authFormFactory from 'consul-ui/components/auth-form/pageobject';
|
||||
import freetextFilterFactory from 'consul-ui/components/freetext-filter/pageobject';
|
||||
|
||||
import searchBarFactory from 'consul-ui/components/search-bar/pageobject';
|
||||
import emptyStateFactory from 'consul-ui/components/empty-state/pageobject';
|
||||
|
||||
import policyFormFactory from 'consul-ui/components/policy-form/pageobject';
|
||||
|
@ -82,11 +79,6 @@ const cancelable = createCancelable(clickable, is);
|
|||
// components
|
||||
const tokenList = tokenListFactory(clickable, attribute, collection, deletable);
|
||||
const authForm = authFormFactory(submitable, clickable, attribute);
|
||||
const freetextFilter = freetextFilterFactory(triggerable);
|
||||
const catalogToolbar = searchBarFactory(freetextFilter);
|
||||
const aclFilter = searchBarFactory(freetextFilter, () =>
|
||||
radiogroup('type', ['', 'management', 'client'])
|
||||
);
|
||||
const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text);
|
||||
const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm);
|
||||
const roleForm = roleFormFactory(submitable, cancelable, policySelector);
|
||||
|
@ -160,18 +152,7 @@ export default {
|
|||
radiogroup
|
||||
)
|
||||
),
|
||||
service: create(
|
||||
service(
|
||||
visitable,
|
||||
clickable,
|
||||
attribute,
|
||||
collection,
|
||||
text,
|
||||
consulIntentionList,
|
||||
catalogToolbar,
|
||||
tabgroup
|
||||
)
|
||||
),
|
||||
service: create(service(visitable, clickable, attribute, collection, text, consulIntentionList, tabgroup)),
|
||||
instance: create(
|
||||
instance(
|
||||
visitable,
|
||||
|
@ -199,7 +180,7 @@ export default {
|
|||
),
|
||||
kvs: create(kvs(visitable, creatable, consulKvList)),
|
||||
kv: create(kv(visitable, attribute, submitable, deletable, cancelable, clickable)),
|
||||
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)),
|
||||
acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection)),
|
||||
acl: create(acl(visitable, submitable, deletable, cancelable, clickable)),
|
||||
policies: create(policies(visitable, creatable, consulPolicyList, popoverSelect)),
|
||||
policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export default function(visitable, deletable, creatable, clickable, attribute, collection, filter) {
|
||||
export default function(visitable, deletable, creatable, clickable, attribute, collection) {
|
||||
return creatable({
|
||||
visit: visitable('/:dc/acls'),
|
||||
acls: collection(
|
||||
|
@ -11,6 +11,5 @@ export default function(visitable, deletable, creatable, clickable, attribute, c
|
|||
confirmUse: clickable('[data-test-confirm-use]'),
|
||||
})
|
||||
),
|
||||
filter: filter('[data-test-acl-filter]'),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
export default function(
|
||||
visitable,
|
||||
clickable,
|
||||
attribute,
|
||||
collection,
|
||||
text,
|
||||
intentions,
|
||||
filter,
|
||||
tabs
|
||||
) {
|
||||
export default function(visitable, clickable, attribute, collection, text, intentions, tabs) {
|
||||
const page = {
|
||||
visit: visitable('/:dc/services/:service'),
|
||||
externalSource: attribute('data-test-external-source', '[data-test-external-source]', {
|
||||
|
@ -28,7 +19,6 @@ export default function(
|
|||
'routing',
|
||||
'tags',
|
||||
]),
|
||||
filter: filter(),
|
||||
// TODO: These need to somehow move to subpages
|
||||
instances: collection('.consul-service-instance-list > ul > li:not(:first-child)', {
|
||||
address: text('[data-test-address]'),
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
import { filters } from 'consul-ui/components/search-bar/utils';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Component | search-bar/filters', function() {
|
||||
test('it correctly reshapes the filter data', function(assert) {
|
||||
[
|
||||
// basic filter, returns a single filter button when clicked
|
||||
// resets selected/queryparam to empty
|
||||
{
|
||||
filters: {
|
||||
status: {
|
||||
value: ['passing'],
|
||||
},
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
key: 'status',
|
||||
value: 'passing',
|
||||
selected: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
// basic filters, returns multiple filter button when clicked
|
||||
// sets selected/queryparam to the left over single filter
|
||||
{
|
||||
filters: {
|
||||
status: {
|
||||
value: ['passing', 'warning'],
|
||||
},
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
key: 'status',
|
||||
value: 'passing',
|
||||
selected: ['warning'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'warning',
|
||||
selected: ['passing'],
|
||||
},
|
||||
],
|
||||
},
|
||||
// basic filters, returns multiple filter button when clicked
|
||||
// sets selected/queryparam to the left over multiple filters
|
||||
{
|
||||
filters: {
|
||||
status: {
|
||||
value: ['passing', 'warning', 'critical'],
|
||||
},
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
key: 'status',
|
||||
value: 'passing',
|
||||
selected: ['warning', 'critical'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'warning',
|
||||
selected: ['passing', 'critical'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'critical',
|
||||
selected: ['passing', 'warning'],
|
||||
},
|
||||
],
|
||||
},
|
||||
// basic filters, returns multiple filter button when clicked
|
||||
// sets selected/queryparam to the left over multiple filters
|
||||
// also search property multiple filter, sets the selected/queryparam to
|
||||
// the left of single searchproperty filter
|
||||
{
|
||||
filters: {
|
||||
status: {
|
||||
value: ['passing', 'warning', 'critical'],
|
||||
},
|
||||
searchproperties: {
|
||||
default: ['Node', 'Address', 'Meta'],
|
||||
value: ['Node', 'Address'],
|
||||
},
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
key: 'status',
|
||||
value: 'passing',
|
||||
selected: ['warning', 'critical'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'warning',
|
||||
selected: ['passing', 'critical'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'critical',
|
||||
selected: ['passing', 'warning'],
|
||||
},
|
||||
{
|
||||
key: 'searchproperties',
|
||||
value: 'Node',
|
||||
selected: ['Address'],
|
||||
},
|
||||
{
|
||||
key: 'searchproperties',
|
||||
value: 'Address',
|
||||
selected: ['Node'],
|
||||
},
|
||||
],
|
||||
},
|
||||
// basic filters, returns multiple filter button when clicked
|
||||
// sets selected/queryparam to the left over multiple filters
|
||||
// also search property single filter, resets the selected/queryparam to
|
||||
// empty
|
||||
{
|
||||
filters: {
|
||||
status: {
|
||||
value: ['passing', 'warning', 'critical'],
|
||||
},
|
||||
searchproperties: {
|
||||
default: ['Node', 'Address', 'Meta'],
|
||||
value: ['Node'],
|
||||
},
|
||||
},
|
||||
expected: [
|
||||
{
|
||||
key: 'status',
|
||||
value: 'passing',
|
||||
selected: ['warning', 'critical'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'warning',
|
||||
selected: ['passing', 'critical'],
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
value: 'critical',
|
||||
selected: ['passing', 'warning'],
|
||||
},
|
||||
{
|
||||
key: 'searchproperties',
|
||||
value: 'Node',
|
||||
selected: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
].forEach(item => {
|
||||
const actual = filters(item.filters);
|
||||
assert.deepEqual(actual, item.expected);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -20,7 +20,7 @@ module('Unit | Filter | Predicates | intention', function() {
|
|||
expected = [items[0]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
accesses: ['allow'],
|
||||
access: ['allow'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -28,7 +28,7 @@ module('Unit | Filter | Predicates | intention', function() {
|
|||
expected = [items[1]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
accesses: ['deny'],
|
||||
access: ['deny'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -36,7 +36,7 @@ module('Unit | Filter | Predicates | intention', function() {
|
|||
expected = items;
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
accesses: ['allow', 'deny'],
|
||||
access: ['allow', 'deny'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
|
|
@ -20,7 +20,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[0]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
instances: ['registered'],
|
||||
instance: ['registered'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -28,7 +28,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[1]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
instances: ['not-registered'],
|
||||
instance: ['not-registered'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -36,7 +36,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = items;
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
instances: ['registered', 'not-registered'],
|
||||
instance: ['registered', 'not-registered'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -60,7 +60,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[0]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
statuses: ['passing'],
|
||||
status: ['passing'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -68,7 +68,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[1]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
statuses: ['warning'],
|
||||
status: ['warning'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -76,7 +76,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = items;
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
statuses: ['passing', 'warning', 'critical'],
|
||||
status: ['passing', 'warning', 'critical'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -98,7 +98,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[0]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
kinds: ['ingress-gateway'],
|
||||
kind: ['ingress-gateway'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -106,7 +106,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[1]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
kinds: ['mesh-gateway'],
|
||||
kind: ['mesh-gateway'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -114,7 +114,7 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = items;
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
kinds: ['ingress-gateway', 'mesh-gateway', 'service'],
|
||||
kind: ['ingress-gateway', 'mesh-gateway', 'service'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -142,9 +142,9 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[0]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
kinds: ['ingress-gateway'],
|
||||
statuses: ['passing'],
|
||||
instances: ['registered'],
|
||||
kind: ['ingress-gateway'],
|
||||
status: ['passing'],
|
||||
instance: ['registered'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -152,9 +152,9 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = [items[1]];
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
kinds: ['mesh-gateway'],
|
||||
statuses: ['warning'],
|
||||
instances: ['registered'],
|
||||
kind: ['mesh-gateway'],
|
||||
status: ['warning'],
|
||||
instance: ['registered'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
@ -162,9 +162,9 @@ module('Unit | Filter | Predicates | service', function() {
|
|||
expected = items;
|
||||
actual = items.filter(
|
||||
predicate({
|
||||
kinds: ['ingress-gateway', 'mesh-gateway', 'service'],
|
||||
statuses: ['passing', 'warning', 'critical'],
|
||||
instances: ['registered', 'not-registered'],
|
||||
kind: ['ingress-gateway', 'mesh-gateway', 'service'],
|
||||
status: ['passing', 'warning', 'critical'],
|
||||
instance: ['registered', 'not-registered'],
|
||||
})
|
||||
);
|
||||
assert.deepEqual(actual, expected);
|
||||
|
|
|
@ -1 +1,158 @@
|
|||
common:
|
||||
brand:
|
||||
consul: Consul
|
||||
terraform: Terraform
|
||||
nomad: Nomad
|
||||
vault: Vault
|
||||
aws: AWS
|
||||
kubernetes: Kubernetes
|
||||
ui:
|
||||
remove: Remove {item}
|
||||
filtered-by: Filtered by {item}
|
||||
name: Name
|
||||
creation: Creation
|
||||
consul:
|
||||
name: Name
|
||||
passing: Passing
|
||||
warning: Warning
|
||||
critical: Critical
|
||||
registered: Registered
|
||||
not-registered: Not Registered
|
||||
empty: No checks
|
||||
tags: Tags
|
||||
service: Service
|
||||
gateway: Gateway
|
||||
mesh: Mesh
|
||||
ingress-gateway: Ingress Gateway
|
||||
terminating-gateway: Terminating Gateway
|
||||
mesh-gateway: Mesh Gateway
|
||||
status: Health Status
|
||||
service-name: Service Name
|
||||
node-name: Node Name
|
||||
accessorid: AccessorID
|
||||
datacenter: Datacenter
|
||||
localbindaddress: Local Bind Address
|
||||
localbindport: Local Bind Port
|
||||
destinationname: Destination Name
|
||||
sourcename: Source Name
|
||||
search:
|
||||
search: Search
|
||||
searchproperty: Search Across
|
||||
source: Source
|
||||
critical: Failing
|
||||
in-mesh: In service mesh
|
||||
not-in-mesh: Not in service mesh
|
||||
sort:
|
||||
alpha:
|
||||
asc: A to Z
|
||||
desc: Z to A
|
||||
numeric:
|
||||
asc: Ascending
|
||||
desc: Descending
|
||||
age:
|
||||
asc: Oldest to Newest
|
||||
desc: Newest to Oldest
|
||||
status:
|
||||
asc: Unhealthy to Healthy
|
||||
desc: Healthy to Unhealthy
|
||||
|
||||
components:
|
||||
consul:
|
||||
service:
|
||||
search-bar:
|
||||
kind: Service Type
|
||||
in-mesh: In service mesh
|
||||
not-in-mesh: Not in service mesh
|
||||
upstream:
|
||||
search-bar:
|
||||
instance:
|
||||
name: Type
|
||||
service-instance:
|
||||
search-bar:
|
||||
sort:
|
||||
name:
|
||||
name: Service Name
|
||||
health-check:
|
||||
search-bar:
|
||||
kind:
|
||||
name: Kind
|
||||
options:
|
||||
service: Service Check
|
||||
node: Node Check
|
||||
check:
|
||||
name: Type
|
||||
options:
|
||||
alias: alias
|
||||
docker: docker
|
||||
grpc: grpc
|
||||
http: http
|
||||
script: script
|
||||
serf: serf
|
||||
tcp: tcp
|
||||
ttl: ttl
|
||||
sort:
|
||||
name:
|
||||
name: Check Name
|
||||
kind:
|
||||
name: Check Type
|
||||
asc: Service to Node
|
||||
desc: Node to Service
|
||||
acl:
|
||||
search-bar:
|
||||
kind:
|
||||
name: Type
|
||||
options:
|
||||
management: Management
|
||||
client: Client
|
||||
token:
|
||||
search-bar:
|
||||
kind:
|
||||
name: Type
|
||||
options:
|
||||
global-management: Global Management
|
||||
global: Global Scope
|
||||
local: Local Scope
|
||||
policy:
|
||||
search-bar:
|
||||
kind:
|
||||
name: Type
|
||||
options:
|
||||
global-management: Global Management
|
||||
standard: Standard
|
||||
kv:
|
||||
search-bar:
|
||||
kind:
|
||||
name: Type
|
||||
options:
|
||||
folder: Folder
|
||||
key: Key
|
||||
sort:
|
||||
kind:
|
||||
asc: Folders to Keys
|
||||
desc: Keys to Folders
|
||||
intention:
|
||||
search-bar:
|
||||
access:
|
||||
name: Permission
|
||||
options:
|
||||
allow: Allow
|
||||
deny: Deny
|
||||
app-aware: App aware
|
||||
sort:
|
||||
access:
|
||||
name: Permission
|
||||
asc: Allow to Deny
|
||||
desc: Deny to Allow
|
||||
source-name:
|
||||
name: Source
|
||||
asc: "Source: A to Z"
|
||||
desc: "Source: Z to A"
|
||||
destination-name:
|
||||
name: Destination
|
||||
asc: "Destination: A to Z"
|
||||
desc: "Destination: Z to A"
|
||||
precedence:
|
||||
name: Precedence
|
||||
asc: Ascending
|
||||
desc: Descending
|
||||
|
||||
|
|
Loading…
Reference in New Issue