-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ui: HealthCheck Search/Sort/Filtering (#9314)
* Adds model layer changes around HealthChecks 1. Makes a HealthCheck model fragment and uses it in ServiceInstances and Nodes 2. Manually adds a relationship between a ServiceInstance and its potential ServiceInstanceProxy 3. Misc changes related to the above such as an Exposed property on MeshChecks, MeshChecks itself * Add a potential temporary endpoint to distinguish ProxyServiceInstance * Fix up Node search bar class * Add search/sort/filter logic * Fixup Service default sort key * Add Healthcheck search/sort/filtering * Tweak CSS add a default Type of 'Serf' when type is blank * Fix up tests and new test support * Add ability to search on Service/Node name depending on where you are * Fixup CheckID search predicate * Use computed for DataCollection to use caching * Alpha sort the Type menu * Temporary fix for new non-changing style Ember Proxys * Only special case EventSource proxies
- Loading branch information
Showing
29 changed files
with
557 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
ui/packages/consul-ui/app/components/consul/health-check/list/pageobject.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export default (collection, text) => (scope = '.consul-health-check-list') => { | ||
return { | ||
scope, | ||
item: collection('li', { | ||
name: text('header h3'), | ||
type: text('[data-health-check-type]'), | ||
exposed: text('[data-test-exposed]'), | ||
}), | ||
}; | ||
}; |
140 changes: 140 additions & 0 deletions
140
ui/packages/consul-ui/app/components/consul/health-check/search-bar/index.hbs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
<form | ||
class="consul-health-check-search-bar filter-bar" | ||
...attributes | ||
> | ||
<div class="search"> | ||
<FreetextFilter | ||
@onsearch={{action @onsearch}} | ||
@value={{@search}} | ||
@placeholder="Search" | ||
> | ||
<PopoverSelect | ||
class="type-search-properties" | ||
@position="right" | ||
@onchange={{action @onfilter.searchproperty}} | ||
@multiple={{true}} | ||
as |components|> | ||
<BlockSlot @name="selected"> | ||
<span> | ||
Search across | ||
</span> | ||
</BlockSlot> | ||
<BlockSlot @name="options"> | ||
{{#let components.Optgroup components.Option as |Optgroup Option|}} | ||
{{#each @searchproperties as |prop|}} | ||
<Option @value={{prop}} @selected={{contains prop @filter.searchproperties}}>{{prop}}</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 | ||
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> | ||
<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> | ||
<Optgroup @label="Check Type"> | ||
<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> |
2 changes: 1 addition & 1 deletion
2
ui/packages/consul-ui/app/components/consul/node/search-bar/index.hbs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
ui/packages/consul-ui/app/filter/predicates/health-check.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export default { | ||
statuses: { | ||
passing: (item, value) => item.Status === value, | ||
warning: (item, value) => item.Status === value, | ||
critical: (item, value) => item.Status === value, | ||
}, | ||
kinds: { | ||
service: (item, value) => item.Kind === value, | ||
node: (item, value) => item.Kind === value, | ||
}, | ||
checks: { | ||
serf: (item, value) => item.Type === '', | ||
script: (item, value) => item.Type === value, | ||
http: (item, value) => item.Type === value, | ||
tcp: (item, value) => item.Type === value, | ||
ttl: (item, value) => item.Type === value, | ||
docker: (item, value) => item.Type === value, | ||
grpc: (item, value) => item.Type === value, | ||
alias: (item, value) => item.Type === value, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Fragment from 'ember-data-model-fragments/fragment'; | ||
import { array } from 'ember-data-model-fragments/attributes'; | ||
import { attr } from '@ember-data/model'; | ||
import { computed } from '@ember/object'; | ||
|
||
export const schema = { | ||
Status: { | ||
allowedValues: ['passing', 'warning', 'critical'], | ||
}, | ||
Type: { | ||
allowedValues: ['', 'script', 'http', 'tcp', 'ttl', 'docker', 'grpc', 'alias'], | ||
}, | ||
}; | ||
|
||
export default class HealthCheck extends Fragment { | ||
@attr('string') Name; | ||
@attr('string') CheckID; | ||
@attr('string') Type; | ||
@attr('string') Status; | ||
@attr('string') Notes; | ||
@attr('string') Output; | ||
@attr('string') ServiceName; | ||
@attr('string') ServiceID; | ||
@attr('string') Node; | ||
@array('string') ServiceTags; | ||
@attr() Definition; // {} | ||
|
||
// Exposed is only set correct if this Check is accessed via instance.MeshChecks | ||
// essentially this is a lazy MeshHealthCheckModel | ||
@attr('boolean') Exposed; | ||
|
||
@computed('ServiceID') | ||
get Kind() { | ||
return this.ServiceID === '' ? 'node' : 'service'; | ||
} | ||
|
||
@computed('Type') | ||
get Exposable() { | ||
return ['http', 'grpc'].includes(this.Type); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import Model, { attr, belongsTo } from '@ember-data/model'; | ||
import { computed } from '@ember/object'; | ||
import { fragmentArray } from 'ember-data-model-fragments/attributes'; | ||
import { computed, get, set } from '@ember/object'; | ||
import { or, filter, alias } from '@ember/object/computed'; | ||
|
||
export const PRIMARY_KEY = 'uid'; | ||
|
@@ -15,7 +16,7 @@ export default class ServiceInstance extends Model { | |
@attr() Proxy; | ||
@attr() Node; | ||
@attr() Service; | ||
@attr() Checks; | ||
@fragmentArray('health-check') Checks; | ||
@attr('number') SyncTime; | ||
@attr() meta; | ||
|
||
|
@@ -29,8 +30,35 @@ export default class ServiceInstance extends Model { | |
@alias('Service.Tags') Tags; | ||
@alias('Service.Meta') Meta; | ||
@alias('Service.Namespace') Namespace; | ||
@filter('Checks.[]', (item, i, arr) => item.ServiceID !== '') ServiceChecks; | ||
@filter('Checks.[]', (item, i, arr) => item.ServiceID === '') NodeChecks; | ||
|
||
@filter('[email protected]', (item, i, arr) => item.Kind === 'service') ServiceChecks; | ||
@filter('[email protected]', (item, i, arr) => item.Kind === 'node') NodeChecks; | ||
|
||
// MeshChecks are a concatenation of Checks for the Instance and Checks for | ||
// the ProxyInstance. Checks is an ember-data-model-fragment, so we can't just | ||
// concat it, we have to loop through all the items in order to merge | ||
@computed('Checks', 'ProxyInstance.Checks', 'ProxyInstance.ServiceProxy.Expose.Checks') | ||
get MeshChecks() { | ||
return (get(this, 'Checks') || []) | ||
.map(item => { | ||
set( | ||
item, | ||
'Exposed', | ||
get(this, 'ProxyInstance.ServiceProxy.Expose.Checks') && get(item, 'Exposable') | ||
); | ||
return item; | ||
}) | ||
.concat( | ||
(get(this, 'ProxyInstance.Checks') || []).map(item => { | ||
set( | ||
item, | ||
'Exposed', | ||
get(this, 'ProxyInstance.ServiceProxy.Expose.Checks') && get(item, 'Exposable') | ||
); | ||
return item; | ||
}) | ||
); | ||
} | ||
|
||
@computed('Service.Meta') | ||
get ExternalSources() { | ||
|
Oops, something went wrong.