ui: Move healthcheck ordering to use new comparators (#8096)
This commit is contained in:
parent
2162f8a4fa
commit
d2515ed409
|
@ -1,47 +1,48 @@
|
||||||
<ul>
|
<div>
|
||||||
{{#each (sort-by (action 'sortChecksByImportance') items) as |item| }}
|
<ul>
|
||||||
{{! TODO: this component and its child should be moved to a single component }}
|
{{#each items as |item| }}
|
||||||
<HealthcheckOutput class={{item.Status}} @tagName="li">
|
<li class={{concat 'healthcheck-output ' item.Status}}>
|
||||||
<BlockSlot @name="header">
|
<div>
|
||||||
<h3>{{item.Name}}</h3>
|
<header>
|
||||||
</BlockSlot>
|
<h3>{{item.Name}}</h3>
|
||||||
<BlockSlot @name="content">
|
</header>
|
||||||
<dl>
|
<dl>
|
||||||
{{#if (eq item.ServiceName "")}}
|
{{#if (eq item.ServiceName "")}}
|
||||||
<dt>NodeName</dt>
|
<dt>NodeName</dt>
|
||||||
<dd>{{item.Node}}</dd>
|
<dd>{{item.Node}}</dd>
|
||||||
{{else}}
|
{{else}}
|
||||||
<dt>ServiceName</dt>
|
<dt>ServiceName</dt>
|
||||||
<dd>{{item.ServiceName}}</dd>
|
<dd>{{item.ServiceName}}</dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>CheckID</dt>
|
<dt>CheckID</dt>
|
||||||
<dd>{{or item.CheckID '-'}}</dd>
|
<dd>{{or item.CheckID '-'}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Type</dt>
|
<dt>Type</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{{item.Type}}
|
{{item.Type}}
|
||||||
{{#if (and exposed (contains item.Type (array 'http' 'grpc')))}}
|
{{#if (and exposed (contains item.Type (array 'http' 'grpc')))}}
|
||||||
<em data-test-exposed="true" data-tooltip="Expose.checks is set to true, so all registered HTTP and gRPC check paths are exposed through Envoy for the Consul agent.">Exposed</em>
|
<em data-test-exposed="true" data-tooltip="Expose.checks is set to true, so all registered HTTP and gRPC check paths are exposed through Envoy for the Consul agent.">Exposed</em>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Notes</dt>
|
<dt>Notes</dt>
|
||||||
<dd>{{or item.Notes '-'}}</dd>
|
<dd>{{or item.Notes '-'}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
{{#if (not-eq item.Type 'ttl')}}
|
{{#if (not-eq item.Type 'ttl')}}
|
||||||
<dt>Output</dt>
|
<dt>Output</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<pre><code>{{item.Output}}</code></pre>
|
<pre><code>{{item.Output}}</code></pre>
|
||||||
<CopyButton @value={{item.Output}} @name="output" />
|
<CopyButton @value={{item.Output}} @name="output" />
|
||||||
</dd>
|
</dd>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</dl>
|
</dl>
|
||||||
</BlockSlot>
|
</div>
|
||||||
</HealthcheckOutput>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,36 +1,5 @@
|
||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
import { get } from '@ember/object';
|
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
// TODO: Could potentially do this on attr change
|
tagName: '',
|
||||||
actions: {
|
|
||||||
sortChecksByImportance: function(a, b) {
|
|
||||||
const statusA = get(a, 'Status');
|
|
||||||
const statusB = get(b, 'Status');
|
|
||||||
switch (statusA) {
|
|
||||||
case 'passing':
|
|
||||||
// a = passing
|
|
||||||
// unless b is also passing then a is less important
|
|
||||||
return statusB === 'passing' ? 0 : 1;
|
|
||||||
case 'critical':
|
|
||||||
// a = critical
|
|
||||||
// unless b is also critical then a is more important
|
|
||||||
return statusB === 'critical' ? 0 : -1;
|
|
||||||
case 'warning':
|
|
||||||
// a = warning
|
|
||||||
switch (statusB) {
|
|
||||||
// b is passing so a is more important
|
|
||||||
case 'passing':
|
|
||||||
return -1;
|
|
||||||
// b is critical so a is less important
|
|
||||||
case 'critical':
|
|
||||||
return 1;
|
|
||||||
// a and b are both warning, therefore equal
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{{! TODO: this component and its parent should be moved to a single component }}
|
|
||||||
{{yield}}
|
|
||||||
<div>
|
|
||||||
<header>
|
|
||||||
<YieldSlot @name="header">{{yield}}</YieldSlot>
|
|
||||||
</header>
|
|
||||||
<YieldSlot @name="content">{{yield}}</YieldSlot>
|
|
||||||
</div>
|
|
|
@ -1,6 +0,0 @@
|
||||||
import Component from '@ember/component';
|
|
||||||
import Slotted from 'block-slots';
|
|
||||||
|
|
||||||
export default Component.extend(Slotted, {
|
|
||||||
classNames: ['healthcheck-output'],
|
|
||||||
});
|
|
|
@ -23,34 +23,4 @@ export default Controller.extend(WithEventSource, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
actions: {
|
|
||||||
sortChecksByImportance: function(a, b) {
|
|
||||||
const statusA = get(a, 'Status');
|
|
||||||
const statusB = get(b, 'Status');
|
|
||||||
switch (statusA) {
|
|
||||||
case 'passing':
|
|
||||||
// a = passing
|
|
||||||
// unless b is also passing then a is less important
|
|
||||||
return statusB === 'passing' ? 0 : 1;
|
|
||||||
case 'critical':
|
|
||||||
// a = critical
|
|
||||||
// unless b is also critical then a is more important
|
|
||||||
return statusB === 'critical' ? 0 : -1;
|
|
||||||
case 'warning':
|
|
||||||
// a = warning
|
|
||||||
switch (statusB) {
|
|
||||||
// b is passing so a is more important
|
|
||||||
case 'passing':
|
|
||||||
return -1;
|
|
||||||
// b is critical so a is less important
|
|
||||||
case 'critical':
|
|
||||||
return 1;
|
|
||||||
// a and b are both warning, therefore equal
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import service from 'consul-ui/sort/comparators/service';
|
import service from 'consul-ui/sort/comparators/service';
|
||||||
|
import check from 'consul-ui/sort/comparators/check';
|
||||||
|
|
||||||
export function initialize(container) {
|
export function initialize(container) {
|
||||||
// Service-less injection using private properties at a per-project level
|
// Service-less injection using private properties at a per-project level
|
||||||
const Sort = container.resolveRegistration('service:sort');
|
const Sort = container.resolveRegistration('service:sort');
|
||||||
const comparators = {
|
const comparators = {
|
||||||
service: service(),
|
service: service(),
|
||||||
|
check: check(),
|
||||||
};
|
};
|
||||||
Sort.reopen({
|
Sort.reopen({
|
||||||
comparator: function(type) {
|
comparator: function(type) {
|
||||||
|
|
42
ui-v2/app/sort/comparators/check.js
Normal file
42
ui-v2/app/sort/comparators/check.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
export default () => key => {
|
||||||
|
if (key.startsWith('Status:')) {
|
||||||
|
return function(itemA, itemB) {
|
||||||
|
const [, dir] = key.split(':');
|
||||||
|
let a, b;
|
||||||
|
if (dir === 'asc') {
|
||||||
|
a = itemA;
|
||||||
|
b = itemB;
|
||||||
|
} else {
|
||||||
|
b = itemA;
|
||||||
|
a = itemB;
|
||||||
|
}
|
||||||
|
const statusA = a.Status;
|
||||||
|
const statusB = b.Status;
|
||||||
|
switch (statusA) {
|
||||||
|
case 'passing':
|
||||||
|
// a = passing
|
||||||
|
// unless b is also passing then a is less important
|
||||||
|
return statusB === 'passing' ? 0 : 1;
|
||||||
|
case 'critical':
|
||||||
|
// a = critical
|
||||||
|
// unless b is also critical then a is more important
|
||||||
|
return statusB === 'critical' ? 0 : -1;
|
||||||
|
case 'warning':
|
||||||
|
// a = warning
|
||||||
|
switch (statusB) {
|
||||||
|
// b is passing so a is more important
|
||||||
|
case 'passing':
|
||||||
|
return -1;
|
||||||
|
// b is critical so a is less important
|
||||||
|
case 'critical':
|
||||||
|
return 1;
|
||||||
|
// a and b are both warning, therefore equal
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
};
|
|
@ -1,7 +1,7 @@
|
||||||
<div id="health-checks" class="tab-section">
|
<div id="health-checks" class="tab-section">
|
||||||
<div role="tabpanel">
|
<div role="tabpanel">
|
||||||
{{#if (gt item.Checks.length 0) }}
|
{{#if (gt item.Checks.length 0) }}
|
||||||
<HealthcheckList @items={{item.Checks}} />
|
<HealthcheckList @items={{sort-by (comparator 'check' 'Status:asc') item.Checks}} />
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>
|
<p>
|
||||||
This node has no health checks.
|
This node has no health checks.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div role="tabpanel">
|
<div role="tabpanel">
|
||||||
{{#if (gt item.ServiceChecks.length 0) }}
|
{{#if (gt item.ServiceChecks.length 0) }}
|
||||||
<section data-test-service-checks>
|
<section data-test-service-checks>
|
||||||
<HealthcheckList @items={{item.ServiceChecks}} @exposed={{proxy.ServiceProxy.Expose.Checks}} />
|
<HealthcheckList @items={{sort-by (comparator 'check' 'Status:asc') item.ServiceChecks}} @exposed={{proxy.ServiceProxy.Expose.Checks}} />
|
||||||
</section>
|
</section>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>
|
<p>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (gt item.NodeChecks.length 0) }}
|
{{#if (gt item.NodeChecks.length 0) }}
|
||||||
<section data-test-node-checks>
|
<section data-test-node-checks>
|
||||||
<HealthcheckList @items={{item.NodeChecks}} />
|
<HealthcheckList @items={{sort-by (comparator 'check' 'Status:asc') item.NodeChecks}} />
|
||||||
</section>
|
</section>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -140,7 +140,7 @@
|
||||||
{{#if (or (gt proxy.ServiceChecks.length 0) (gt proxy.NodeChecks.length 0))}}
|
{{#if (or (gt proxy.ServiceChecks.length 0) (gt proxy.NodeChecks.length 0))}}
|
||||||
<section>
|
<section>
|
||||||
<h3>Proxy health</h3>
|
<h3>Proxy health</h3>
|
||||||
<HealthcheckList data-test-proxy-checks @items={{append proxy.ServiceChecks proxy.NodeChecks}} />
|
<HealthcheckList data-test-proxy-checks @items={{sort-by (comparator 'check' 'Status:asc') (append proxy.ServiceChecks proxy.NodeChecks)}} />
|
||||||
</section>
|
</section>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import { module, test } from 'qunit';
|
|
||||||
import { setupRenderingTest } from 'ember-qunit';
|
|
||||||
import { render, find } from '@ember/test-helpers';
|
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
|
||||||
|
|
||||||
module('Integration | Component | healthcheck output', function(hooks) {
|
|
||||||
setupRenderingTest(hooks);
|
|
||||||
|
|
||||||
test('it renders', async function(assert) {
|
|
||||||
// Set any properties with this.set('myProperty', 'value');
|
|
||||||
// Handle any actions with this.on('myAction', function(val) { ... });
|
|
||||||
|
|
||||||
await render(hbs`{{healthcheck-output}}`);
|
|
||||||
|
|
||||||
assert.equal(find('*').textContent.trim(), '');
|
|
||||||
|
|
||||||
// Template block usage:
|
|
||||||
await render(hbs`
|
|
||||||
{{#healthcheck-output}}{{/healthcheck-output}}
|
|
||||||
`);
|
|
||||||
assert.equal(find('*').textContent.trim(), '');
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in a new issue