Add filtering for 'unknown' imported services

This commit is contained in:
Michael Klein 2022-10-11 11:24:10 +02:00
parent 42a725bffe
commit 71e20c3122
6 changed files with 209 additions and 200 deletions

View File

@ -1,12 +1,13 @@
<Route @name={{routeName}} as |route|>
<DataLoader
@src={{uri
"/${partition}/${nspace}/${dc}/services/${peer}"
"/${partition}/${nspace}/${dc}/services/${peer}/${peerId}"
(hash
partition=route.params.partition
nspace=route.params.nspace
dc=route.params.dc
peer=route.model.peer.Name
peerId=route.model.peer.id
)
}}
as |api|
@ -61,6 +62,7 @@
@onsearch={{action (mut search) value="target.value"}}
@sort={{sort}}
@filter={{filters}}
@peer={{route.model.peer}}
/>
{{/let}}
{{/if}}
@ -76,7 +78,6 @@
<Consul::Service::List
@items={{collection.items}}
@partition={{partition}}
@peer={{route.model.peer}}
/>
</collection.Collection>
<collection.Empty>

View File

@ -6,35 +6,12 @@
as |item index|
>
<BlockSlot @name='header'>
{{#let
(eq @peer.State 'FAILING')
(and @peer (eq item.InstanceCount 0))
as |peerIsFailing peeredAndInstanceCountZero|
}}
<dl class={{if (or peerIsFailing peeredAndInstanceCountZero) 'help' item.MeshStatus}}>
<dt>
Health
</dt>
<dd>
<Tooltip @position='top-start'>
{{#if peerIsFailing}}
This peer is out of sync, so the current health statuses of its services are unknown.
{{else if peeredAndInstanceCountZero}}
This service currently has 0 instances. Check with the operator of its peer to make
sure this is expected behavior.
{{else if (eq 'critical' item.MeshStatus)}}
At least one health check on one instance is failing.
{{else if (eq 'warning' item.MeshStatus)}}
At least one health check on one instance has a warning.
{{else if (eq 'passing' item.MeshStatus)}}
All health checks are passing.
{{else}}
There are no health checks.
{{/if}}
</Tooltip>
</dd>
</dl>
{{/let}}
<dl class={{item.MeshStatus}}>
<dt>
Health
</dt>
<dd {{tooltip item.healthTooltipText}}></dd>
</dl>
{{#if (gt item.InstanceCount 0)}}
<a
data-test-service-name
@ -70,7 +47,8 @@
{{pluralize item.InstanceCount 'instance' without-count=true}}
</span>
{{/if}}
{{#unless @peer}}
{{! we are displaying imported-services - don't show bucket-list }}
{{#unless item.peer}}
<Consul::Bucket::List @item={{item}} @nspace={{@nspace}} @partition={{@partition}} />
{{/unless}}
{{#if (eq item.Kind 'terminating-gateway')}}

View File

@ -1,195 +1,208 @@
<SearchBar
class="consul-service-search-bar"
...attributes
@filter={{@filter}}
>
<:status as |search|>
<SearchBar class='consul-service-search-bar' ...attributes @filter={{@filter}}>
<: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)
{{#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)
(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)}}
>
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}}
{{/let}}
</:status>
<:search as |search|>
<search.Search
@onsearch={{action @onsearch}}
@value={{@search}}
@placeholder={{t "common.search.search"}}
</: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|
>
<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|}}
<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={{includes prop @filter.searchproperty.value}}>
{{t (concat "common.consul." (lowercase prop))}}
{{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>
{{t "common.consul.status"}}
</span>
</BlockSlot>
<BlockSlot @name="options">
{{#let components.Optgroup components.Option as |Optgroup Option|}}
{{#each (array "passing" "warning" "critical" "empty") as |state|}}
<Option class="value-{{state}}" @value={{state}} @selected={{includes state @filter.status.value}}>
{{t (concat "common.consul." state)
default=(array
(concat "common.search." state)
)
}}
</Option>
{{/each}}
{{/let}}
{{/let}}
</BlockSlot>
</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={{includes 'service' @filter.kind.value}}>
{{t "common.consul.service"}}
</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>
{{t 'common.consul.status'}}
</span>
</BlockSlot>
<BlockSlot @name='options'>
{{#let components.Optgroup components.Option as |Optgroup Option|}}
{{#each this.healthStates as |state|}}
<Option
class='value-{{state}}'
@value={{state}}
@selected={{includes state @filter.status.value}}
>
{{t (concat 'common.consul.' state) default=(array (concat 'common.search.' state))}}
</Option>
{{/each}}
{{/let}}
</BlockSlot>
</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={{includes '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={{includes kind @filter.kind.value}}>
{{t (concat "common.consul." kind)}}
</Option>
{{/each}}
<Optgroup @label={{t 'common.consul.gateway'}}>
{{#each (array 'ingress-gateway' 'terminating-gateway' 'mesh-gateway') as |kind|}}
<Option @value={{kind}} @selected={{includes 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={{includes state @filter.kind.value}}>
{{t (concat "common.search." state)}}
</Option>
{{/each}}
<Optgroup @label={{t 'common.consul.mesh'}}>
{{#each (array 'in-mesh' 'not-in-mesh') as |state|}}
<Option @value={{state}} @selected={{includes state @filter.kind.value}}>
{{t (concat 'common.search.' state)}}
</Option>
{{/each}}
</Optgroup>
{{/let}}
</BlockSlot>
</search.Select>
{{#if (gt @sources.length 0)}}
{{/let}}
</BlockSlot>
</search.Select>
{{#if (gt @sources.length 0)}}
<search.Select
class="type-source"
@position="left"
class='type-source'
@position='left'
@onchange={{action @filter.source.change}}
@multiple={{true}}
as |components|>
<BlockSlot @name="selected">
as |components|
>
<BlockSlot @name='selected'>
<span>
{{t "common.search.source"}}
{{t 'common.search.source'}}
</span>
</BlockSlot>
<BlockSlot @name="options">
{{#let components.Option as |Option|}}
{{#if (gt @sources.length 0)}}
{{#each @sources as |source|}}
<Option class={{source}} @value={{source}} @selected={{includes source @filter.source.value}}>
{{t (concat "common.brand." source)}}
</Option>
{{/each}}
<Option class="consul" @value='consul' @selected={{includes 'consul' @filter.source.value}}>
{{t 'common.brand.consul'}}
</Option>
{{/if}}
{{/let}}
<BlockSlot @name='options'>
{{#let components.Option as |Option|}}
{{#if (gt @sources.length 0)}}
{{#each @sources as |source|}}
<Option
class={{source}}
@value={{source}}
@selected={{includes source @filter.source.value}}
>
{{t (concat 'common.brand.' source)}}
</Option>
{{/each}}
<Option
class='consul'
@value='consul'
@selected={{includes 'consul' @filter.source.value}}
>
{{t 'common.brand.consul'}}
</Option>
{{/if}}
{{/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>
{{/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 @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>
{{/let}}
</BlockSlot>
</search.Select>
</:sort>
</SearchBar>

View File

@ -0,0 +1,13 @@
import Component from '@glimmer/component';
export default class ConsulServiceSearchBar extends Component {
get healthStates() {
let states = ['passing', 'warning', 'critical', 'empty'];
if (this.args.peer) {
states = [...states, 'unknown'];
}
return states;
}
}

View File

@ -25,8 +25,8 @@
@extend %with-minus-square-fill-mask, %as-pseudo;
color: rgb(var(--tone-gray-500));
}
%icon-definition.empty dt::before,
%composite-row-header .help dd::before {
%icon-definition.unknown dt::before,
%composite-row-header .unknown dd::before {
@extend %with-help-circle-outline-mask, %as-pseudo;
color: rgb(var(--tone-gray-500));
}

View File

@ -42,6 +42,10 @@
@extend %with-minus-square-fill-mask, %as-pseudo;
color: rgb(var(--tone-gray-400));
}
%popover-select .value-unknown button::before {
@extend %with-help-circle-outline-mask, %as-pseudo;
color: rgb(var(--tone-gray-500));
}
%popover-select.type-source li:not(.partition) button {
text-transform: capitalize;
}