Skip to content

Commit

Permalink
System Batch UI, Client Status Bar Chart and Client Tab page view (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
ChaiWithJai authored Oct 7, 2021
1 parent c50b751 commit 0564f9f
Show file tree
Hide file tree
Showing 48 changed files with 2,112 additions and 44 deletions.
16 changes: 13 additions & 3 deletions ui/.prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
printWidth: 100
singleQuote: true
trailingComma: es5
{
"printWidth": 100,
"singleQuote": true,
"trailingComma": "es5",
"overrides": [
{
"files": "*.hbs",
"options": {
"singleQuote": false
}
}
]
}
4 changes: 3 additions & 1 deletion ui/app/components/allocation-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ export default class AllocationRow extends Component {
do {
if (this.stats) {
try {
yield this.get('stats.poll').perform();
yield this.get('stats.poll')
.linked()
.perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
Expand Down
19 changes: 16 additions & 3 deletions ui/app/components/distribution-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const sumAggregate = (total, val) => total + val;
export default class DistributionBar extends Component.extend(WindowResizable) {
chart = null;
@overridable(() => null) data;
onSliceClick = null;
activeDatum = null;
isNarrow = false;

Expand All @@ -33,11 +34,13 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
const data = copy(this.data, true);
const sum = data.mapBy('value').reduce(sumAggregate, 0);

return data.map(({ label, value, className, layers }, index) => ({
return data.map(({ label, value, className, layers, legendLink, help }, index) => ({
label,
value,
className,
layers,
legendLink,
help,
index,
percent: value / sum,
offset:
Expand Down Expand Up @@ -121,8 +124,14 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
const activeDatum = this.activeDatum;
const isActive = activeDatum && activeDatum.label === d.label;
const isInactive = activeDatum && activeDatum.label !== d.label;
return [ className, isActive && 'active', isInactive && 'inactive' ].compact().join(' ');
});
const isClickable = !!this.onSliceClick;
return [
className,
isActive && 'active',
isInactive && 'inactive',
isClickable && 'clickable'
].compact().join(' ');
}).attr('data-test-slice-label', d => d.className);

this.set('slices', slices);

Expand Down Expand Up @@ -172,6 +181,10 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
.attr('height', '6px')
.attr('y', '50%');
}

if (this.onSliceClick) {
slices.on('click', this.onSliceClick);
}
}
/* eslint-enable */

Expand Down
120 changes: 120 additions & 0 deletions ui/app/components/job-client-status-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { computed } from '@ember/object';
import DistributionBar from './distribution-bar';
import classic from 'ember-classic-decorator';

@classic
export default class JobClientStatusBar extends DistributionBar {
layoutName = 'components/distribution-bar';

'data-test-job-client-status-bar' = true;
job = null;
jobClientStatus = null;

@computed('job.namespace', 'jobClientStatus.byStatus')
get data() {
const {
queued,
starting,
running,
complete,
degraded,
failed,
lost,
notScheduled,
} = this.jobClientStatus.byStatus;

return [
{
label: 'Queued',
value: queued.length,
className: 'queued',
legendLink: {
queryParams: {
status: JSON.stringify(['queued']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Starting',
value: starting.length,
className: 'starting',
legendLink: {
queryParams: {
status: JSON.stringify(['starting']),
namespace: this.job.namespace.get('id'),
},
},
layers: 2,
},
{
label: 'Running',
value: running.length,
className: 'running',
legendLink: {
queryParams: {
status: JSON.stringify(['running']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Complete',
value: complete.length,
className: 'complete',
legendLink: {
queryParams: {
status: JSON.stringify(['complete']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Degraded',
value: degraded.length,
className: 'degraded',
legendLink: {
queryParams: {
status: JSON.stringify(['degraded']),
namespace: this.job.namespace.get('id'),
},
},
help: 'Some allocations for this job were not successfull or did not run.',
},
{
label: 'Failed',
value: failed.length,
className: 'failed',
legendLink: {
queryParams: {
status: JSON.stringify(['failed']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Lost',
value: lost.length,
className: 'lost',
legendLink: {
queryParams: {
status: JSON.stringify(['lost']),
namespace: this.job.namespace.get('id'),
},
},
},
{
label: 'Not Scheduled',
value: notScheduled.length,
className: 'not-scheduled',
legendLink: {
queryParams: {
status: JSON.stringify(['notScheduled']),
namespace: this.job.namespace.get('id'),
},
},
help: 'No allocations for this job were scheduled into these clients.',
},
];
}
}
89 changes: 89 additions & 0 deletions ui/app/components/job-client-status-row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import EmberObject from '@ember/object';
import Component from '@glimmer/component';

export default class ClientRow extends Component {
// Attribute set in the template as @onClick.
onClick() {}

get row() {
return this.args.row.model;
}

get shouldDisplayAllocationSummary() {
return this.args.row.model.jobStatus !== 'notScheduled';
}

get allocationSummaryPlaceholder() {
switch (this.args.row.model.jobStatus) {
case 'notScheduled':
return 'Not Scheduled';
default:
return '';
}
}

get humanizedJobStatus() {
switch (this.args.row.model.jobStatus) {
case 'notScheduled':
return 'not scheduled';
default:
return this.args.row.model.jobStatus;
}
}

get jobStatusClass() {
switch (this.args.row.model.jobStatus) {
case 'notScheduled':
return 'not-scheduled';
default:
return this.args.row.model.jobStatus;
}
}

get allocationContainer() {
const statusSummary = {
queuedAllocs: 0,
completeAllocs: 0,
failedAllocs: 0,
runningAllocs: 0,
startingAllocs: 0,
lostAllocs: 0,
};

switch (this.args.row.model.jobStatus) {
case 'notSchedule':
break;
case 'queued':
statusSummary.queuedAllocs = this.args.row.model.allocations.length;
break;
case 'starting':
statusSummary.startingAllocs = this.args.row.model.allocations.length;
break;
default:
for (const alloc of this.args.row.model.allocations) {
switch (alloc.clientStatus) {
case 'running':
statusSummary.runningAllocs++;
break;
case 'lost':
statusSummary.lostAllocs++;
break;
case 'failed':
statusSummary.failedAllocs++;
break;
case 'complete':
statusSummary.completeAllocs++;
break;
case 'starting':
statusSummary.startingAllocs++;
break;
}
}
}

const Allocations = EmberObject.extend({
...statusSummary,
});
return Allocations.create();
}
}
9 changes: 9 additions & 0 deletions ui/app/components/job-page/parameterized-child.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import PeriodicChildJobPage from './periodic-child';
import classic from 'ember-classic-decorator';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

@classic
export default class ParameterizedChild extends PeriodicChildJobPage {
@alias('job.decodedPayload') payload;
@service store;

@computed('payload')
get payloadJSON() {
Expand All @@ -17,4 +20,10 @@ export default class ParameterizedChild extends PeriodicChildJobPage {
}
return json;
}

@jobClientStatus('nodes', 'job') jobClientStatus;

get nodes() {
return this.store.peekAll('node');
}
}
28 changes: 28 additions & 0 deletions ui/app/components/job-page/parts/job-client-status-summary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Component from '@ember/component';
import { action, computed } from '@ember/object';
import { classNames } from '@ember-decorators/component';
import classic from 'ember-classic-decorator';

@classic
@classNames('boxed-section')
export default class JobClientStatusSummary extends Component {
job = null;
jobClientStatus = null;
gotoClients() {}

@computed
get isExpanded() {
const storageValue = window.localStorage.nomadExpandJobClientStatusSummary;
return storageValue != null ? JSON.parse(storageValue) : true;
}

@action
onSliceClick(slice) {
this.gotoClients([slice.className.camelize()]);
}

persist(item, isOpen) {
window.localStorage.nomadExpandJobClientStatusSummary = isOpen;
this.notifyPropertyChange('isExpanded');
}
}
5 changes: 4 additions & 1 deletion ui/app/components/job-page/parts/summary.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import classic from 'ember-classic-decorator';
@classNames('boxed-section')
export default class Summary extends Component {
job = null;
forceCollapsed = false;

@computed
@computed('forceCollapsed')
get isExpanded() {
if (this.forceCollapsed) return false;

const storageValue = window.localStorage.nomadExpandJobSummary;
return storageValue != null ? JSON.parse(storageValue) : true;
}
Expand Down
10 changes: 10 additions & 0 deletions ui/app/components/job-page/periodic-child.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import AbstractJobPage from './abstract';
import { computed } from '@ember/object';
import { inject as service } from '@ember/service';
import classic from 'ember-classic-decorator';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

@classic
export default class PeriodicChild extends AbstractJobPage {
@service store;

@computed('job.{name,id}', 'job.parent.{name,id}')
get breadcrumbs() {
const job = this.job;
Expand All @@ -21,4 +25,10 @@ export default class PeriodicChild extends AbstractJobPage {
},
];
}

@jobClientStatus('nodes', 'job') jobClientStatus;

get nodes() {
return this.store.peekAll('node');
}
}
15 changes: 15 additions & 0 deletions ui/app/components/job-page/sysbatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import AbstractJobPage from './abstract';
import classic from 'ember-classic-decorator';
import { inject as service } from '@ember/service';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';

@classic
export default class Sysbatch extends AbstractJobPage {
@service store;

@jobClientStatus('nodes', 'job') jobClientStatus;

get nodes() {
return this.store.peekAll('node');
}
}
Loading

0 comments on commit 0564f9f

Please sign in to comment.