Create a new task route hierarchy

Drilling into a task from an allocation transitions to the task
heirarchy.
This commit is contained in:
Michael Lange
2017-10-30 13:39:15 -07:00
parent 4847b308fe
commit 0d2efb0f1a
10 changed files with 166 additions and 112 deletions

View File

@@ -1,17 +1,5 @@
import Ember from 'ember';
import Sortable from 'nomad-ui/mixins/sortable';
const { Controller, computed } = Ember;
const { Controller } = Ember;
export default Controller.extend(Sortable, {
queryParams: {
sortProperty: 'sort',
sortDescending: 'desc',
},
sortProperty: 'name',
sortDescending: false,
listToSort: computed.alias('model.states'),
sortedStates: computed.alias('listSorted'),
});
export default Controller.extend({});

View File

@@ -0,0 +1,17 @@
import Ember from 'ember';
import Sortable from 'nomad-ui/mixins/sortable';
const { Controller, computed } = Ember;
export default Controller.extend(Sortable, {
queryParams: {
sortProperty: 'sort',
sortDescending: 'desc',
},
sortProperty: 'name',
sortDescending: false,
listToSort: computed.alias('model.states'),
sortedStates: computed.alias('listSorted'),
});

View File

@@ -25,7 +25,11 @@ Router.map(function() {
});
this.route('allocations', function() {
this.route('allocation', { path: '/:allocation_id' });
this.route('allocation', { path: '/:allocation_id' }, function() {
this.route('task', { path: '/:name' }, function() {
this.route('logs');
});
});
});
this.route('settings', function() {

View File

@@ -0,0 +1,22 @@
import Ember from 'ember';
const { Route, inject, Error: EmberError } = Ember;
export default Route.extend({
store: inject.service(),
model({ name }) {
const allocation = this.modelFor('allocations.allocation');
if (allocation) {
const task = allocation.get('states').findBy('name', name);
if (task) {
return task;
}
const err = new EmberError(`Task ${name} not found for allocation ${allocation.get('id')}`);
err.code = '404';
this.controllerFor('application').set('error', err);
}
},
});

View File

@@ -1,8 +1,3 @@
<div class="page-layout">
{{#global-header class="page-header"}}
Allocations
{{/global-header}}
{{#gutter-menu class="page-body"}}
{{outlet}}
{{/gutter-menu}}
{{outlet}}
</div>

View File

@@ -1,91 +1 @@
<section class="section">
<h1 class="title">Allocation {{model.name}}</h1>
<h3 class="subtitle">
For job {{#link-to "jobs.job" model.job (query-params jobNamespace=model.job.namespace.id)}}{{model.job.name}}{{/link-to}}
on client {{#link-to "clients.client" model.node}}{{model.node.shortId}}{{/link-to}}
</h3>
<div class="message">
<div class="message-header">
Tasks
</div>
{{#list-table
source=sortedStates
sortProperty=sortProperty
sortDescending=sortDescending
class="is-striped tasks" as |t|}}
{{#t.head}}
{{#t.sort-by prop="name"}}Name{{/t.sort-by}}
{{#t.sort-by prop="state"}}State{{/t.sort-by}}
<th>Last Event</th>
{{#t.sort-by prop="events.lastObject.time"}}Time{{/t.sort-by}}
<th>Addresses</th>
{{/t.head}}
{{#t.body as |row|}}
<tr>
<td>{{row.model.task.name}}</td>
<td>{{row.model.state}}</td>
<td>
{{#if row.model.events.lastObject.displayMessage}}
{{row.model.events.lastObject.displayMessage}}
{{else}}
<em>No message</em>
{{/if}}
</td>
<td>{{moment-format row.model.events.lastObject.time "MM/DD/YY HH:mm:ss [UTC]"}}</td>
<td>
<ul>
{{#each row.model.resources.networks.firstObject.reservedPorts as |port|}}
<li>
<strong>{{port.Label}}:</strong>
<a href="http://{{row.model.allocation.node.address}}:{{port.Value}}" target="_blank">{{row.model.allocation.node.address}}:{{port.Value}}</a>
</li>
{{/each}}
{{#each row.model.resources.networks.firstObject.dynamicPorts as |port|}}
<li>
<strong>{{port.Label}}:</strong>
<a href="http://{{row.model.allocation.node.address}}:{{port.Value}}" target="_blank">{{row.model.allocation.node.address}}:{{port.Value}}</a>
</li>
{{/each}}
</ul>
</td>
</tr>
{{/t.body}}
{{/list-table}}
</div>
{{#each model.states as |state|}}
<div class="message task-state-events">
<div class="message-header">
{{state.task.name}} ({{state.state}}) Started: {{moment-format state.startedAt "MM/DD/YY HH:mm:ss [UTC]"}}
{{#unless state.isActive}}
Ended: {{moment-format state.finishedAt "MM/DD/YY HH:mm:ss [UTC]"}}
{{/unless}}
</div>
<table class="table is-striped task-events">
<thead>
<tr>
<td class="is-3">Time</td>
<td class="is-1">Type</td>
<td>Description</td>
</tr>
</thead>
<tbody>
{{#each (reverse state.events) as |event|}}
<tr>
<td>{{moment-format event.time "MM/DD/YY HH:mm:ss [UTC]"}}</td>
<td>{{event.type}}</td>
<td>
{{#if event.displayMessage}}
{{event.displayMessage}}
{{else}}
<em>No message</em>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
{{/each}}
</section>
{{outlet}}

View File

@@ -0,0 +1,100 @@
{{#global-header class="page-header"}}
Allocations
{{/global-header}}
{{#gutter-menu class="page-body"}}
<section class="section">
<h1 class="title">Allocation {{model.name}}</h1>
<h3 class="subtitle">
For job {{#link-to "jobs.job" model.job (query-params jobNamespace=model.job.namespace.id)}}{{model.job.name}}{{/link-to}}
on client {{#link-to "clients.client" model.node}}{{model.node.shortId}}{{/link-to}}
</h3>
<div class="message">
<div class="message-header">
Tasks
</div>
{{#list-table
source=sortedStates
sortProperty=sortProperty
sortDescending=sortDescending
class="is-striped tasks" as |t|}}
{{#t.head}}
{{#t.sort-by prop="name"}}Name{{/t.sort-by}}
{{#t.sort-by prop="state"}}State{{/t.sort-by}}
<th>Last Event</th>
{{#t.sort-by prop="events.lastObject.time"}}Time{{/t.sort-by}}
<th>Addresses</th>
{{/t.head}}
{{#t.body as |row|}}
<tr>
<td>
{{#link-to "allocations.allocation.task" row.model.allocation row.model}}
{{row.model.task.name}}
{{/link-to}}
</td>
<td>{{row.model.state}}</td>
<td>
{{#if row.model.events.lastObject.displayMessage}}
{{row.model.events.lastObject.displayMessage}}
{{else}}
<em>No message</em>
{{/if}}
</td>
<td>{{moment-format row.model.events.lastObject.time "MM/DD/YY HH:mm:ss [UTC]"}}</td>
<td>
<ul>
{{#each row.model.resources.networks.firstObject.reservedPorts as |port|}}
<li>
<strong>{{port.Label}}:</strong>
<a href="http://{{row.model.allocation.node.address}}:{{port.Value}}" target="_blank">{{row.model.allocation.node.address}}:{{port.Value}}</a>
</li>
{{/each}}
{{#each row.model.resources.networks.firstObject.dynamicPorts as |port|}}
<li>
<strong>{{port.Label}}:</strong>
<a href="http://{{row.model.allocation.node.address}}:{{port.Value}}" target="_blank">{{row.model.allocation.node.address}}:{{port.Value}}</a>
</li>
{{/each}}
</ul>
</td>
</tr>
{{/t.body}}
{{/list-table}}
</div>
{{#each model.states as |state|}}
<div class="message task-state-events">
<div class="message-header">
{{state.task.name}} ({{state.state}}) Started: {{moment-format state.startedAt "MM/DD/YY HH:mm:ss [UTC]"}}
{{#unless state.isActive}}
Ended: {{moment-format state.finishedAt "MM/DD/YY HH:mm:ss [UTC]"}}
{{/unless}}
</div>
<table class="table is-striped task-events">
<thead>
<tr>
<td class="is-3">Time</td>
<td class="is-1">Type</td>
<td>Description</td>
</tr>
</thead>
<tbody>
{{#each (reverse state.events) as |event|}}
<tr>
<td>{{moment-format event.time "MM/DD/YY HH:mm:ss [UTC]"}}</td>
<td>{{event.type}}</td>
<td>
{{#if event.displayMessage}}
{{event.displayMessage}}
{{else}}
<em>No message</em>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
{{/each}}
</section>
{{/gutter-menu}}

View File

@@ -0,0 +1 @@
{{outlet}}

View File

@@ -0,0 +1,12 @@
{{#global-header class="page-header"}}
{{/global-header}}
{{#gutter-menu class="page-body"}}
{{partial "allocations/allocation/task/subnav"}}
<section class="section">
<ul>
<li>Name: {{model.name}}</li>
<li>State: {{model.state}}</li>
<li>CPU: {{model.resources.cpu}}</li>
</ul>
</section>
{{/gutter-menu}}

View File

@@ -0,0 +1,5 @@
<div class="tabs is-subnav">
<ul>
<li>{{#link-to "allocations.allocation.task.index" task.allocation task activeClass="is-active"}}Overview{{/link-to}}</li>
</ul>
</div>