mirror of https://github.com/status-im/consul.git
ui: Add ability to sort service based on health (#7989)
* ui: Add ability to sort service based on health * ui: Move custom sorting to sort/comparator Service/Helper (like search) This moves custom sorting to use the same pattern as custom searching. * Remove old Controller based comparator
This commit is contained in:
parent
d295d976ce
commit
7949410208
|
@ -0,0 +1,9 @@
|
||||||
|
import Helper from '@ember/component/helper';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
|
export default Helper.extend({
|
||||||
|
sort: service('sort'),
|
||||||
|
compute([type, key], hash) {
|
||||||
|
return this.sort.comparator(type)(key);
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
import service from 'consul-ui/sort/comparators/service';
|
||||||
|
|
||||||
|
export function initialize(container) {
|
||||||
|
// Service-less injection using private properties at a per-project level
|
||||||
|
const Sort = container.resolveRegistration('service:sort');
|
||||||
|
const comparators = {
|
||||||
|
service: service(),
|
||||||
|
};
|
||||||
|
Sort.reopen({
|
||||||
|
comparator: function(type) {
|
||||||
|
return comparators[type];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
initialize,
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
import Service from '@ember/service';
|
||||||
|
export default Service.extend({
|
||||||
|
comparator: function(type) {},
|
||||||
|
});
|
|
@ -0,0 +1,37 @@
|
||||||
|
export default () => key => {
|
||||||
|
if (key.startsWith('Status:')) {
|
||||||
|
return function(serviceA, serviceB) {
|
||||||
|
const [, dir] = key.split(':');
|
||||||
|
let a, b;
|
||||||
|
if (dir === 'asc') {
|
||||||
|
b = serviceA;
|
||||||
|
a = serviceB;
|
||||||
|
} else {
|
||||||
|
a = serviceA;
|
||||||
|
b = serviceB;
|
||||||
|
}
|
||||||
|
switch (true) {
|
||||||
|
case a.ChecksCritical > b.ChecksCritical:
|
||||||
|
return 1;
|
||||||
|
case a.ChecksCritical < b.ChecksCritical:
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
switch (true) {
|
||||||
|
case a.ChecksWarning > b.ChecksWarning:
|
||||||
|
return 1;
|
||||||
|
case a.ChecksWarning < b.ChecksWarning:
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
switch (true) {
|
||||||
|
case a.ChecksPassing < b.ChecksPassing:
|
||||||
|
return 1;
|
||||||
|
case a.ChecksPassing > b.ChecksPassing:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
};
|
|
@ -2,6 +2,8 @@
|
||||||
{{#let (selectable-key-values
|
{{#let (selectable-key-values
|
||||||
(array "Name:asc" "A to Z")
|
(array "Name:asc" "A to Z")
|
||||||
(array "Name:desc" "Z to A")
|
(array "Name:desc" "Z to A")
|
||||||
|
(array "Status:asc" "Unhealthy to Healthy")
|
||||||
|
(array "Status:desc" "Healthy to Unhealthy")
|
||||||
selected=sortBy
|
selected=sortBy
|
||||||
)
|
)
|
||||||
as |sort|
|
as |sort|
|
||||||
|
@ -29,7 +31,8 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="content">
|
<BlockSlot @name="content">
|
||||||
<ChangeableSet @dispatcher={{searchable 'service' (sort-by sort.selected.key services)}} @terms={{search}}>
|
{{#let (sort-by (comparator 'service' sort.selected.key) services) as |sorted|}}
|
||||||
|
<ChangeableSet @dispatcher={{searchable 'service' sorted}} @terms={{search}}>
|
||||||
<BlockSlot @name="set" as |filtered|>
|
<BlockSlot @name="set" as |filtered|>
|
||||||
<ConsulServiceList @routeName="dc.services.show" @items={{filtered}} @proxies={{proxies}}/>
|
<ConsulServiceList @routeName="dc.services.show" @items={{filtered}} @proxies={{proxies}}/>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
@ -64,6 +67,7 @@
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ChangeableSet>
|
</ChangeableSet>
|
||||||
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</AppView>
|
</AppView>
|
||||||
{{/let}}
|
{{/let}}
|
||||||
|
|
|
@ -1,45 +1,85 @@
|
||||||
@setupApplicationTest
|
@setupApplicationTest
|
||||||
Feature: dc / services / sorting
|
Feature: dc / services / sorting
|
||||||
Scenario:
|
Scenario:
|
||||||
Given 1 datacenter model with the value "dc-1"
|
Given 1 datacenter model with the value "dc-1"
|
||||||
And 6 service models from yaml
|
And 6 service models from yaml
|
||||||
---
|
---
|
||||||
- Name: Service-A
|
- Name: Service-A
|
||||||
Kind: ~
|
Kind: ~
|
||||||
- Name: Service-B
|
ChecksPassing: 1
|
||||||
Kind: ~
|
ChecksWarning: 1
|
||||||
- Name: Service-C
|
ChecksCritical: 3
|
||||||
Kind: ~
|
- Name: Service-B
|
||||||
- Name: Service-D
|
Kind: ~
|
||||||
Kind: ~
|
ChecksPassing: 1
|
||||||
- Name: Service-E
|
ChecksWarning: 1
|
||||||
Kind: ~
|
ChecksCritical: 5
|
||||||
- Name: Service-F
|
- Name: Service-C
|
||||||
Kind: ~
|
Kind: ~
|
||||||
---
|
ChecksPassing: 1
|
||||||
When I visit the services page for yaml
|
ChecksWarning: 1
|
||||||
---
|
ChecksCritical: 4
|
||||||
dc: dc-1
|
- Name: Service-D
|
||||||
---
|
Kind: ~
|
||||||
When I click selected on the sort
|
ChecksPassing: 1
|
||||||
When I click options.1.button on the sort
|
ChecksWarning: 5
|
||||||
Then I see name on the services vertically like yaml
|
ChecksCritical: 1
|
||||||
---
|
- Name: Service-E
|
||||||
- Service-F
|
Kind: ~
|
||||||
- Service-E
|
ChecksPassing: 1
|
||||||
- Service-D
|
ChecksWarning: 3
|
||||||
- Service-C
|
ChecksCritical: 1
|
||||||
- Service-B
|
- Name: Service-F
|
||||||
- Service-A
|
Kind: ~
|
||||||
---
|
ChecksPassing: 1
|
||||||
When I click selected on the sort
|
ChecksWarning: 4
|
||||||
When I click options.0.button on the sort
|
ChecksCritical: 1
|
||||||
Then I see name on the services vertically like yaml
|
---
|
||||||
---
|
When I visit the services page for yaml
|
||||||
- Service-A
|
---
|
||||||
- Service-B
|
dc: dc-1
|
||||||
- Service-C
|
---
|
||||||
- Service-D
|
When I click selected on the sort
|
||||||
- Service-E
|
When I click options.1.button on the sort
|
||||||
- Service-F
|
Then I see name on the services vertically like yaml
|
||||||
---
|
---
|
||||||
|
- Service-F
|
||||||
|
- Service-E
|
||||||
|
- Service-D
|
||||||
|
- Service-C
|
||||||
|
- Service-B
|
||||||
|
- Service-A
|
||||||
|
---
|
||||||
|
When I click selected on the sort
|
||||||
|
When I click options.0.button on the sort
|
||||||
|
Then I see name on the services vertically like yaml
|
||||||
|
---
|
||||||
|
- Service-A
|
||||||
|
- Service-B
|
||||||
|
- Service-C
|
||||||
|
- Service-D
|
||||||
|
- Service-E
|
||||||
|
- Service-F
|
||||||
|
---
|
||||||
|
When I click selected on the sort
|
||||||
|
When I click options.2.button on the sort
|
||||||
|
Then I see name on the services vertically like yaml
|
||||||
|
---
|
||||||
|
- Service-B
|
||||||
|
- Service-C
|
||||||
|
- Service-A
|
||||||
|
- Service-D
|
||||||
|
- Service-F
|
||||||
|
- Service-E
|
||||||
|
---
|
||||||
|
When I click selected on the sort
|
||||||
|
When I click options.3.button on the sort
|
||||||
|
Then I see name on the services vertically like yaml
|
||||||
|
---
|
||||||
|
- Service-E
|
||||||
|
- Service-F
|
||||||
|
- Service-D
|
||||||
|
- Service-A
|
||||||
|
- Service-C
|
||||||
|
- Service-B
|
||||||
|
---
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupTest } from 'ember-qunit';
|
||||||
|
|
||||||
|
module('Unit | Service | sort', function(hooks) {
|
||||||
|
setupTest(hooks);
|
||||||
|
|
||||||
|
// Replace this with your real tests.
|
||||||
|
test('it exists', function(assert) {
|
||||||
|
let service = this.owner.lookup('service:sort');
|
||||||
|
assert.ok(service);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,56 @@
|
||||||
|
import comparatorFactory from 'consul-ui/sort/comparators/service';
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
|
||||||
|
module('Unit | Sort | Comparator | service', function() {
|
||||||
|
const comparator = comparatorFactory();
|
||||||
|
test('Passing anything but Status: just returns what you gave it', function(assert) {
|
||||||
|
const expected = 'Name:asc';
|
||||||
|
const actual = comparator(expected);
|
||||||
|
assert.equal(actual, expected);
|
||||||
|
});
|
||||||
|
test('items are sorted by a fake Status which uses Checks{Passing,Warning,Critical}', function(assert) {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
ChecksPassing: 1,
|
||||||
|
ChecksWarning: 1,
|
||||||
|
ChecksCritical: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ChecksPassing: 1,
|
||||||
|
ChecksWarning: 1,
|
||||||
|
ChecksCritical: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ChecksPassing: 1,
|
||||||
|
ChecksWarning: 1,
|
||||||
|
ChecksCritical: 3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const comp = comparator('Status:asc');
|
||||||
|
assert.equal(typeof comp, 'function');
|
||||||
|
|
||||||
|
const expected = [
|
||||||
|
{
|
||||||
|
ChecksPassing: 1,
|
||||||
|
ChecksWarning: 1,
|
||||||
|
ChecksCritical: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ChecksPassing: 1,
|
||||||
|
ChecksWarning: 1,
|
||||||
|
ChecksCritical: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ChecksPassing: 1,
|
||||||
|
ChecksWarning: 1,
|
||||||
|
ChecksCritical: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let actual = items.sort(comp);
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
|
|
||||||
|
expected.reverse();
|
||||||
|
actual = items.sort(comparator('Status:desc'));
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue