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

Add Allocation Filters in Client View #11545

Merged
merged 13 commits into from
Dec 18, 2021
Merged
65 changes: 63 additions & 2 deletions ui/app/controllers/clients/client/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/* eslint-disable ember/no-observers */
/* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */
import { alias } from '@ember/object/computed';
import Controller from '@ember/controller';
import { action, computed } from '@ember/object';
import { observes } from '@ember-decorators/object';
import { scheduleOnce } from '@ember/runloop';
import { task } from 'ember-concurrency';
import intersection from 'lodash.intersection';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';

@classic
Expand All @@ -27,11 +31,19 @@ export default class ClientController extends Controller.extend(Sortable, Search
{
onlyPreemptions: 'preemptions',
},
{
qpStatus: 'status',
},
{
qpTaskGroup: 'taskGroup',
lgfa29 marked this conversation as resolved.
Show resolved Hide resolved
},
];

// Set in the route
flagAsDraining = false;

qpStatus = '';
qpTaskGroup = '';
currentPage = 1;
pageSize = 8;

Expand All @@ -45,15 +57,35 @@ export default class ClientController extends Controller.extend(Sortable, Search

onlyPreemptions = false;

@computed('model.allocations.[]', 'preemptions.[]', 'onlyPreemptions')
@computed(
'model.allocations.[]',
'preemptions.[]',
'onlyPreemptions',
'selectionStatus',
'selectionTaskGroup'
)
get visibleAllocations() {
return this.onlyPreemptions ? this.preemptions : this.model.allocations;
const allocations = this.onlyPreemptions ? this.preemptions : this.model.allocations;
const { selectionStatus, selectionTaskGroup } = this;

return allocations.filter(alloc => {
if (selectionStatus.length && !selectionStatus.includes(alloc.clientStatus)) {
return false;
}
if (selectionTaskGroup.length && !selectionTaskGroup.includes(alloc.taskGroupName)) {
return false;
}
return true;
});
}

@alias('visibleAllocations') listToSort;
@alias('listSorted') listToSearch;
@alias('listSearched') sortedAllocations;

@selection('qpStatus') selectionStatus;
@selection('qpTaskGroup') selectionTaskGroup;

eligibilityError = null;
stopDrainError = null;
drainError = null;
Expand Down Expand Up @@ -147,4 +179,33 @@ export default class ClientController extends Controller.extend(Sortable, Search
const error = messageFromAdapterError(err) || 'Could not run drain';
this.set('drainError', error);
}

get optionsAllocationStatus() {
return [
{ key: 'queued', label: 'Queued' },
{ key: 'starting', label: 'Starting' },
{ key: 'running', label: 'Running' },
{ key: 'complete', label: 'Complete' },
{ key: 'failed', label: 'Failed' },
{ key: 'lost', label: 'Lost' },
];
}

@computed('model.allocations.[]', 'selectionTaskGroup')
get optionsTaskGroups() {
const taskGroups = Array.from(new Set(this.model.allocations.mapBy('taskGroupName'))).compact();

// Update query param when the list of clients changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
this.set('qpTaskGroup', serialize(intersection(taskGroups, this.selectionTaskGroup)));
});

return taskGroups.sort().map(dc => ({ key: dc, label: dc }));
ChaiWithJai marked this conversation as resolved.
Show resolved Hide resolved
}

@action
setFacetQueryParam(queryParam, selection) {
this.set(queryParam, serialize(selection));
}
}
62 changes: 60 additions & 2 deletions ui/app/controllers/jobs/job/task-group.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
/* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */
import { inject as service } from '@ember/service';
import { alias, readOnly } from '@ember/object/computed';
import Controller from '@ember/controller';
import { action, computed, get } from '@ember/object';
import { scheduleOnce } from '@ember/runloop';
import intersection from 'lodash.intersection';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting';
import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';

@classic
Expand All @@ -29,11 +33,19 @@ export default class TaskGroupController extends Controller.extend(
{
sortDescending: 'desc',
},
{
qpStatus: 'status',
},
{
qpClient: 'client',
},
];

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

qpStatus = '';
qpClient = '';
lgfa29 marked this conversation as resolved.
Show resolved Hide resolved
sortProperty = 'modifyIndex';
sortDescending = true;

Expand All @@ -42,15 +54,32 @@ export default class TaskGroupController extends Controller.extend(
return ['shortId', 'name'];
}

@computed('model.allocations.[]')
@computed('model.allocations.[]', 'selectionStatus', 'selectionClient')
get allocations() {
return this.get('model.allocations') || [];
const allocations = this.get('model.allocations') || [];
const { selectionStatus, selectionClient } = this;

if (!allocations.length) return allocations;

return allocations.filter(alloc => {
if (selectionStatus.length && !selectionStatus.includes(alloc.clientStatus)) {
return false;
}
if (selectionClient.length && !selectionClient.includes(alloc.get('node.shortId'))) {
return false;
}

return true;
});
}

@alias('allocations') listToSort;
@alias('listSorted') listToSearch;
@alias('listSearched') sortedAllocations;

@selection('qpStatus') selectionStatus;
@selection('qpClient') selectionClient;

@computed('model.scaleState.events.@each.time', function() {
const events = get(this, 'model.scaleState.events');
if (events) {
Expand Down Expand Up @@ -83,4 +112,33 @@ export default class TaskGroupController extends Controller.extend(
scaleTaskGroup(count) {
return this.model.scale(count);
}

get optionsAllocationStatus() {
return [
{ key: 'queued', label: 'Queued' },
{ key: 'starting', label: 'Starting' },
{ key: 'running', label: 'Running' },
{ key: 'complete', label: 'Complete' },
{ key: 'failed', label: 'Failed' },
{ key: 'lost', label: 'Lost' },
];
}

@computed('model.allocations.[]', 'selectionClient')
get optionsClients() {
const clients = Array.from(new Set(this.model.allocations.mapBy('node.shortId'))).compact();

// Update query param when the list of clients changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
this.set('qpClient', serialize(intersection(clients, this.selectionClient)));
});

return clients.sort().map(dc => ({ key: dc, label: dc }));
}

@action
setFacetQueryParam(queryParam, selection) {
this.set(queryParam, serialize(selection));
}
}
9 changes: 9 additions & 0 deletions ui/app/styles/components/boxed-section.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
margin-left: auto;
}

.is-subsection {
display: flex;
align-items: baseline;

.is-padded {
padding: 0em 0em 0em 1em;
}
}

.is-fixed-width {
display: inline-block;
width: 8em;
Expand Down
29 changes: 23 additions & 6 deletions ui/app/templates/clients/client/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,29 @@
</button>
{{/if}}
</div>
<SearchBox
@searchTerm={{mut this.searchTerm}}
@onChange={{action this.resetPagination}}
@placeholder="Search allocations..."
@class="is-inline pull-right"
@inputClass="is-compact" />
<div class="pull-right is-subsection">
<MultiSelectDropdown
data-test-allocation-status-facet
@label="Status"
@options={{this.optionsAllocationStatus}}
@selection={{this.selectionStatus}}
@onSelect={{action "setFacetQueryParam" "qpStatus"}}
/>
<MultiSelectDropdown
data-test-allocation-task-group-facet
@label="Task Group"
@options={{this.optionsTaskGroups}}
@selection={{this.selectionTaskGroup}}
@onSelect={{action "setFacetQueryParam" "qpTaskGroup"}}
/>
<SearchBox
@searchTerm={{mut this.searchTerm}}
@onChange={{action this.resetPagination}}
@placeholder="Search allocations..."
@inputClass="is-compact"
@class="is-padded"
/>
</div>
</div>
<div class="boxed-section-body is-full-bleed">
<ListPagination
lgfa29 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
30 changes: 23 additions & 7 deletions ui/app/templates/jobs/job/task-group.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,32 @@
</AllocationStatusBar>
</div>
</div>

<div class="boxed-section">
<div class="boxed-section-head">
Allocations
<SearchBox
@searchTerm={{mut this.searchTerm}}
@placeholder="Search allocations..."
@onChange={{action this.resetPagination}}
@class="is-inline pull-right"
@inputClass="is-compact" />
<div class="pull-right is-subsection">
<MultiSelectDropdown
data-test-allocation-status-facet
@label="Status"
@options={{this.optionsAllocationStatus}}
@selection={{this.selectionStatus}}
@onSelect={{action "setFacetQueryParam" "qpStatus"}}
/>
<MultiSelectDropdown
data-test-allocation-task-group-facet
@label="Client"
@options={{this.optionsClients}}
@selection={{this.selectionClient}}
@onSelect={{action "setFacetQueryParam" "qpClient"}}
/>
<SearchBox
@searchTerm={{mut this.searchTerm}}
@placeholder="Search allocations..."
@onChange={{action this.resetPagination}}
@class="is-padded"
@inputClass="is-compact"
/>
</div>
</div>
<div class="boxed-section-body is-full-bleed">
{{#if this.sortedAllocations}}
Expand Down