Skip to content

Commit

Permalink
create client tab view
Browse files Browse the repository at this point in the history
  • Loading branch information
ChaiWithJai committed Aug 27, 2021
1 parent 38f764f commit 2c96d75
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 1 deletion.
27 changes: 27 additions & 0 deletions ui/app/components/client-row.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<tr>
<th class="is-narrow"></th>

<td data-test-short-id>
<LinkTo @route="clients.client" @model={{this.id}} class="is-primary">
{{this.id}}
</LinkTo>
</td>
<td data-test-short-id>
{{this.name}}
</td>
<td data-test-create-time>{{moment-from-now this.eldestCreateTime}}</td>
<td data-test-modify-time>
<span class="tooltip" aria-label="{{format-month-ts this.node.modifyTime}}">
{{moment-from-now this.allocation.modifyTime}}
</span>
</td>
<td data-test-client-status class="is-one-line">
<span class="color-swatch">{{this.status}}</span>
</td>
<td data-test-client-allocations class="is-one-line">
<div class="inline-chart">
<AllocationStatusBar @allocationContainer={{this.allocationContainer}} @isNarrow={{true}} />
</div>
</td>
</tr>

73 changes: 73 additions & 0 deletions ui/app/components/client-row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { classNames, tagName } from '@ember-decorators/component';
import EmberObject from '@ember/object';
import Component from '@glimmer/component';

@tagName('tr')
@classNames('client-row', 'is-interactive')
export default class ClientRowComponent extends Component {
get id() {
console.log('node arg', this.args.node);
return Object.keys(this.args.node.model)[0];
}

get name() {
return this.args.node.model[this.id][0].name;
}

get eldestCreateTime() {
let eldest = null;
for (const allocation of this.args.node.model[this.id]) {
if (!eldest || allocation.createTime < eldest) {
eldest = allocation.createTime;
}
}
return eldest;
}

get mostRecentModifyTime() {
let mostRecent = null;
for (const allocation of this.args.node.model[this.id]) {
if (!mostRecent || allocation.modifyTime > mostRecent) {
mostRecent = allocation.createTime;
}
}
return mostRecent;
}

get status() {
return this.args.jobClientStatus.byNode[this.id];
}

get allocationContainer() {
const statusSummary = {
queuedAllocs: 0,
completeAllocs: 0,
failedAllocs: 0,
runningAllocs: 0,
startingAllocs: 0,
lostAllocs: 0,
};
for (const allocation of this.args.node.model[this.id]) {
const { clientStatus } = allocation;
switch (clientStatus) {
// add missing statuses
case 'running':
statusSummary.runningAllocs++;
break;
case 'lost':
statusSummary.lostAllocs++;
break;
case 'failed':
statusSummary.failedAllocs++;
break;
case 'completed':
statusSummary.completeAllocs++;
break;
}
}
const Allocations = EmberObject.extend({
...statusSummary,
});
return Allocations.create();
}
}
67 changes: 67 additions & 0 deletions ui/app/controllers/jobs/job/clients.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Controller from '@ember/controller';
import { action, computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

export default class ClientsController extends Controller.extend(
Sortable,
Searchable,
WithNamespaceResetting
) {
queryParams = [
{
currentPage: 'page',
},
{
searchTerm: 'search',
},
{
sortProperty: 'sort',
},
{
sortDescending: 'desc',
},
];

currentPage = 1;
pageSize = 25;

sortProperty = 'modifyIndex';
sortDescending = true;

@alias('model') job;
@jobClientStatus('nodes', 'job.status', 'job.allocations') jobClientStatus;

@alias('uniqueNodes') listToSort;
@alias('listSorted') listToSearch;
@alias('listSearched') sortedClients;

@computed('job')
get uniqueNodes() {
// add datacenter filter
const allocs = this.job.allocations;
const nodes = allocs.mapBy('node');
const uniqueNodes = nodes.uniqBy('id').toArray();
const result = uniqueNodes.map(nodeId => {
return {
[nodeId.get('id')]: allocs
.toArray()
.filter(alloc => nodeId.get('id') === alloc.get('node.id'))
.map(alloc => ({
nodeId,
...alloc.getProperties('clientStatus', 'name', 'createTime', 'modifyTime'),
})),
};
});
return result;
}

@action
gotoClient(client) {
console.log('goToClient', client);
this.transitionToRoute('clients.client', client);
}
}
1 change: 0 additions & 1 deletion ui/app/controllers/jobs/job/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export default class IndexController extends Controller.extend(WithNamespaceRese
.map(alloc => alloc.getProperties('clientStatus', 'name', 'createTime', 'modifyTime')),
};
});
console.log('result\n\n', result);
return result;
}

Expand Down
1 change: 1 addition & 0 deletions ui/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Router.map(function() {
this.route('dispatch');
this.route('evaluations');
this.route('allocations');
this.route('clients');
});
});

Expand Down
3 changes: 3 additions & 0 deletions ui/app/routes/jobs/job/clients.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Route from '@ember/routing/route';

export default class ClientsRoute extends Route {}
1 change: 1 addition & 0 deletions ui/app/templates/components/job-subnav.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
{{/if}}
<li data-test-tab="allocations"><LinkTo @route="jobs.job.allocations" @model={{@job}} @activeClass="is-active">Allocations</LinkTo></li>
<li data-test-tab="evaluations"><LinkTo @route="jobs.job.evaluations" @model={{@job}} @activeClass="is-active">Evaluations</LinkTo></li>
<li data-test-tab="clients"><LinkTo @route="jobs.job.clients" @model={{@job}} @activeClass="is-active">Clients</LinkTo></li>
</ul>
</div>
71 changes: 71 additions & 0 deletions ui/app/templates/jobs/job/clients.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{{page-title "Job " this.job.name " clients"}}
<JobSubnav @job={{this.job}} />
<section class="section">
{{#if this.uniqueNodes.length}}
<div class="content">
<div>
<SearchBox
data-test-clients-search
@searchTerm={{mut this.searchTerm}}
@onChange={{action this.resetPagination}}
@placeholder="Search clients..." />
</div>
</div>
{{#if this.sortedClients}}
<ListPagination
@source={{this.sortedClients}}
@size={{this.pageSize}}
@page={{this.currentPage}}
@class="clients" as |p|>
<ListTable
@source={{p.list}}
@sortProperty={{this.sortProperty}}
@sortDescending={{this.sortDescending}}
@class="with-foot" as |t|>
<t.head>
<th class="is-narrow"></th>
<t.sort-by @prop="id">ID</t.sort-by>
<t.sort-by @prop="name">Name</t.sort-by>
<t.sort-by @prop="createIndex" @title="Create Index">Created</t.sort-by>
<t.sort-by @prop="modifyIndex" @title="Modify Index">Modified</t.sort-by>
<t.sort-by @prop="statusIndex">Status</t.sort-by>
<th class="is-3">Allocation Summary</th>
</t.head>
<t.body as |row|>
{{!-- {{log this.sortedClients.length}} --}}
<ClientRow
@data-test-client={{'sdf'}}
@jobClientStatus={{this.jobClientStatus}}
@node={{row}}
@context="job"
@onClick={{action "gotoClient" row }} />
</t.body>
</ListTable>
<div class="table-foot">
<nav class="pagination">
<div class="pagination-numbers">
{{p.startsAt}}&ndash;{{p.endsAt}} of {{this.sortedClients.length}}
</div>
<p.prev @class="pagination-previous"> &lt; </p.prev>
<p.next @class="pagination-next"> &gt; </p.next>
<ul class="pagination-list"></ul>
</nav>
</div>
</ListPagination>
{{else}}
<div class="boxed-section-body">
<div class="empty-message" data-test-empty-clients-list>
<h3 class="empty-message-headline" data-test-empty-clients-list-headline>No Matches</h3>
<p class="empty-message-body">No clients match the term <strong>{{this.searchTerm}}</strong></p>
</div>
</div>
{{/if}}
{{else}}
<div class="boxed-section-body">
<div class="empty-message" data-test-empty-clients-list>
<h3 class="empty-message-headline" data-test-empty-clients-list-headline>No Clients</h3>
<p class="empty-message-body">No clients have been placed.</p>
</div>
</div>
{{/if}}
</section>
8 changes: 8 additions & 0 deletions ui/app/utils/properties/job-client-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export default function jobClientStatus(nodesKey, jobStatusKey, jobAllocsKey) {
return {
byNode: {
'123': 'running',
'14b8ff31-8310-4877-b3e9-ba6ebcbf37a2': 'running',
'193538ac-30d7-48eb-9a31-b89a83abae1d': 'degraded',
'0cdce07c-6c50-4364-9ffd-e08c419f93aa': 'lost',
'a07563e7-fdc6-4df4-bfd7-82b97a3605ab': 'failed',
'6c32bb4d-6fda-4c0d-a7be-008f857d9f0e': 'queued',
'75930e1c-15f2-4411-8dbd-1016e3d54c12': 'running',
'8f834f8f-75cc-4da7-96f2-3665bd9bf774': 'running',
'386a8b5f-68ab-4baf-a5ca-597d1bed8589': 'running',
},
byStatus: {
running: ['123'],
Expand Down

0 comments on commit 2c96d75

Please sign in to comment.