Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ui] node eligibilty taken into consideration when clients list filtered to "ready" #18607

Merged
3 changes: 3 additions & 0 deletions .changelog/18607.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui: change the State filter on clients page to split out eligibility and drain status
```
30 changes: 12 additions & 18 deletions ui/app/components/client-node-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,37 +57,31 @@ export default class ClientNodeRow extends Component.extend(

@watchRelationship('allocations') watch;

@computed('node.compositeStatus')
@computed('node.status')
get nodeStatusColor() {
let compositeStatus = this.get('node.compositeStatus');

if (compositeStatus === 'draining') {
return 'neutral';
} else if (compositeStatus === 'ineligible') {
let status = this.get('node.status');
if (status === 'disconnected') {
return 'warning';
} else if (compositeStatus === 'down') {
} else if (status === 'down') {
return 'critical';
} else if (compositeStatus === 'ready') {
} else if (status === 'ready') {
return 'success';
} else if (compositeStatus === 'initializing') {
} else if (status === 'initializing') {
return 'neutral';
} else {
return 'neutral';
}
}
@computed('node.compositeStatus')
@computed('node.status')
get nodeStatusIcon() {
let compositeStatus = this.get('node.compositeStatus');

if (compositeStatus === 'draining') {
return 'minus-circle';
} else if (compositeStatus === 'ineligible') {
let status = this.get('node.status');
if (status === 'disconnected') {
return 'skip';
} else if (compositeStatus === 'down') {
} else if (status === 'down') {
return 'x-circle';
} else if (compositeStatus === 'ready') {
} else if (status === 'ready') {
return 'check-circle';
} else if (compositeStatus === 'initializing') {
} else if (status === 'initializing') {
return 'entry-point';
} else {
return '';
Expand Down
175 changes: 143 additions & 32 deletions ui/app/controllers/clients/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: BUSL-1.1
*/

// @ts-check

/* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */
import { alias, readOnly } from '@ember/object/computed';
import { inject as service } from '@ember/service';
Expand Down Expand Up @@ -45,9 +47,6 @@ export default class IndexController extends Controller.extend(
{
qpClass: 'class',
},
{
qpState: 'state',
},
{
qpDatacenter: 'dc',
},
Expand All @@ -62,6 +61,110 @@ export default class IndexController extends Controller.extend(
},
];

filterFunc = (node) => {
return node.isEligible;
};

clientFilterToggles = {
state: [
{
label: 'initializing',
qp: 'state_initializing',
default: true,
filter: (node) => node.status === 'initializing',
},
{
label: 'ready',
qp: 'state_ready',
default: true,
filter: (node) => node.status === 'ready',
},
{
label: 'down',
qp: 'state_down',
default: true,
filter: (node) => node.status === 'down',
},
{
label: 'disconnected',
qp: 'state_disconnected',
default: true,
filter: (node) => node.status === 'disconnected',
},
],
eligibility: [
{
label: 'eligible',
qp: 'eligibility_eligible',
default: true,
filter: (node) => node.isEligible,
},
{
label: 'ineligible',
qp: 'eligibility_ineligible',
default: true,
filter: (node) => !node.isEligible,
},
],
drainStatus: [
{
label: 'draining',
qp: 'drain_status_draining',
default: true,
filter: (node) => node.isDraining,
},
{
label: 'not draining',
qp: 'drain_status_not_draining',
default: true,
filter: (node) => !node.isDraining,
},
],
};

@computed(
'state_initializing',
'state_ready',
'state_down',
'state_disconnected',
'eligibility_eligible',
'eligibility_ineligible',
'drain_status_draining',
'drain_status_not_draining',
'allToggles.[]'
)
get activeToggles() {
return this.allToggles.filter((t) => this[t.qp]);
}

get allToggles() {
return Object.values(this.clientFilterToggles).reduce(
(acc, filters) => acc.concat(filters),
[]
);
}

// eslint-disable-next-line ember/classic-decorator-hooks
constructor() {
super(...arguments);
this.addDynamicQueryParams();
}

addDynamicQueryParams() {
this.clientFilterToggles.state.forEach((filter) => {
this.queryParams.push({ [filter.qp]: filter.qp });
this.set(filter.qp, filter.default);
});
this.clientFilterToggles.eligibility.forEach((filter) => {
this.queryParams.push({ [filter.qp]: filter.qp });
this.set(filter.qp, filter.default);
});
this.clientFilterToggles.drainStatus.forEach((filter) => {
this.queryParams.push({ [filter.qp]: filter.qp });
this.set(filter.qp, filter.default);
});
}

currentPage = 1;
@readOnly('userSettings.pageSize') pageSize;

Expand All @@ -74,14 +177,12 @@ export default class IndexController extends Controller.extend(
}

qpClass = '';
qpState = '';
qpDatacenter = '';
qpVersion = '';
qpVolume = '';
qpNodePool = '';

@selection('qpClass') selectionClass;
@selection('qpState') selectionState;
@selection('qpDatacenter') selectionDatacenter;
@selection('qpVersion') selectionVersion;
@selection('qpVolume') selectionVolume;
Expand All @@ -105,18 +206,6 @@ export default class IndexController extends Controller.extend(
return classes.sort().map((dc) => ({ key: dc, label: dc }));
}

@computed
get optionsState() {
return [
{ key: 'initializing', label: 'Initializing' },
{ key: 'ready', label: 'Ready' },
{ key: 'down', label: 'Down' },
{ key: 'ineligible', label: 'Ineligible' },
{ key: 'draining', label: 'Draining' },
{ key: 'disconnected', label: 'Disconnected' },
];
}

@computed('nodes.[]', 'selectionDatacenter')
get optionsDatacenter() {
const datacenters = Array.from(
Expand Down Expand Up @@ -195,35 +284,50 @@ export default class IndexController extends Controller.extend(
}

@computed(
'clientFilterToggles',
'drain_status_draining',
'drain_status_not_draining',
'eligibility_eligible',
'eligibility_ineligible',
'nodes.[]',
'selectionClass',
'selectionState',
'selectionDatacenter',
'selectionNodePool',
'selectionVersion',
'selectionVolume'
'selectionVolume',
'state_disconnected',
'state_down',
'state_initializing',
'state_ready'
)
get filteredNodes() {
const {
selectionClass: classes,
selectionState: states,
selectionDatacenter: datacenters,
selectionNodePool: nodePools,
selectionVersion: versions,
selectionVolume: volumes,
} = this;

const onlyIneligible = states.includes('ineligible');
const onlyDraining = states.includes('draining');

// states is a composite of node status and other node states
const statuses = states.without('ineligible').without('draining');

return this.nodes.filter((node) => {
let nodes = this.nodes;

// new QP style filtering
for (let category in this.clientFilterToggles) {
nodes = nodes.filter((node) => {
let includeNode = false;
for (let filter of this.clientFilterToggles[category]) {
if (this[filter.qp] && filter.filter(node)) {
includeNode = true;
break;
}
}
return includeNode;
});
}

return nodes.filter((node) => {
if (classes.length && !classes.includes(node.get('nodeClass')))
return false;
if (statuses.length && !statuses.includes(node.get('status')))
return false;
if (datacenters.length && !datacenters.includes(node.get('datacenter')))
return false;
if (versions.length && !versions.includes(node.get('version')))
Expand All @@ -237,9 +341,6 @@ export default class IndexController extends Controller.extend(
return false;
}

if (onlyIneligible && node.get('isEligible')) return false;
if (onlyDraining && !node.get('isDraining')) return false;

return true;
});
}
Expand All @@ -254,6 +355,16 @@ export default class IndexController extends Controller.extend(
this.set(queryParam, serialize(selection));
}

@action
handleFilterChange(queryParamValue, option, queryParamLabel) {
if (queryParamValue.includes(option)) {
queryParamValue.removeObject(option);
} else {
queryParamValue.addObject(option);
}
this.set(queryParamLabel, serialize(queryParamValue));
}

@action
gotoNode(node) {
this.transitionToRoute('clients.client', node);
Expand Down
6 changes: 6 additions & 0 deletions ui/app/styles/core/table.scss
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@
white-space: nowrap;
}

&.node-status-badges {
.hds-badge__text {
white-space: nowrap;
}
}

&.is-narrow {
padding: 1.25em 0 1.25em 0.5em;

Expand Down
Loading
Loading