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:
John Cowen 2020-06-03 17:07:49 +01:00 committed by John Cowen
parent f4e38d229b
commit 43b320be44
8 changed files with 226 additions and 46 deletions

View File

@ -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);
},
});

View File

@ -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,
};

View File

@ -0,0 +1,4 @@
import Service from '@ember/service';
export default Service.extend({
comparator: function(type) {},
});

View File

@ -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;
};

View File

@ -2,6 +2,8 @@
{{#let (selectable-key-values
(array "Name:asc" "A to Z")
(array "Name:desc" "Z to A")
(array "Status:asc" "Unhealthy to Healthy")
(array "Status:desc" "Healthy to Unhealthy")
selected=sortBy
)
as |sort|
@ -29,7 +31,8 @@
{{/if}}
</BlockSlot>
<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|>
<ConsulServiceList @routeName="dc.services.show" @items={{filtered}} @proxies={{proxies}}/>
</BlockSlot>
@ -64,6 +67,7 @@
</EmptyState>
</BlockSlot>
</ChangeableSet>
{{/let}}
</BlockSlot>
</AppView>
{{/let}}

View File

@ -1,45 +1,85 @@
@setupApplicationTest
Feature: dc / services / sorting
Scenario:
Given 1 datacenter model with the value "dc-1"
And 6 service models from yaml
---
- Name: Service-A
Kind: ~
- Name: Service-B
Kind: ~
- Name: Service-C
Kind: ~
- Name: Service-D
Kind: ~
- Name: Service-E
Kind: ~
- Name: Service-F
Kind: ~
---
When I visit the services page for yaml
---
dc: dc-1
---
When I click selected on the sort
When I click options.1.button on the sort
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
---
@setupApplicationTest
Feature: dc / services / sorting
Scenario:
Given 1 datacenter model with the value "dc-1"
And 6 service models from yaml
---
- Name: Service-A
Kind: ~
ChecksPassing: 1
ChecksWarning: 1
ChecksCritical: 3
- Name: Service-B
Kind: ~
ChecksPassing: 1
ChecksWarning: 1
ChecksCritical: 5
- Name: Service-C
Kind: ~
ChecksPassing: 1
ChecksWarning: 1
ChecksCritical: 4
- Name: Service-D
Kind: ~
ChecksPassing: 1
ChecksWarning: 5
ChecksCritical: 1
- Name: Service-E
Kind: ~
ChecksPassing: 1
ChecksWarning: 3
ChecksCritical: 1
- Name: Service-F
Kind: ~
ChecksPassing: 1
ChecksWarning: 4
ChecksCritical: 1
---
When I visit the services page for yaml
---
dc: dc-1
---
When I click selected on the sort
When I click options.1.button on the sort
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
---

View File

@ -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);
});
});

View File

@ -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);
});
});