Skip to content

Commit

Permalink
Merge pull request #4189 from hashicorp/f-ui-stop-job-button
Browse files Browse the repository at this point in the history
UI: Stop job button
  • Loading branch information
DingoEatingFuzz committed Apr 21, 2018
2 parents 443c1f3 + 10c9e7a commit fb7e0c1
Show file tree
Hide file tree
Showing 24 changed files with 527 additions and 113 deletions.
24 changes: 17 additions & 7 deletions ui/app/adapters/job.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,24 @@ export default Watchable.extend({

forcePeriodic(job) {
if (job.get('periodic')) {
const [path, params] = this.buildURL('job', job.get('id'), job, 'findRecord').split('?');
let url = `${path}/periodic/force`;

if (params) {
url += `?${params}`;
}

const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/periodic/force');
return this.ajax(url, 'POST');
}
},

stop(job) {
const url = this.urlForFindRecord(job.get('id'), 'job');
return this.ajax(url, 'DELETE');
},
});

function addToPath(url, extension = '') {
const [path, params] = url.split('?');
let newUrl = `${path}${extension}`;

if (params) {
newUrl += `?${params}`;
}

return newUrl;
}
12 changes: 12 additions & 0 deletions ui/app/components/job-page/abstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export default Component.extend({
gotoTaskGroup() {},
gotoJob() {},

// Set to a { title, description } to surface an error
errorMessage: null,

breadcrumbs: computed('job.{name,id}', function() {
const job = this.get('job');
return [
Expand All @@ -33,4 +36,13 @@ export default Component.extend({
},
];
}),

actions: {
clearErrorMessage() {
this.set('errorMessage', null);
},
handleError(errorObject) {
this.set('errorMessage', errorObject);
},
},
});
8 changes: 8 additions & 0 deletions ui/app/components/job-page/parts/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Component from '@ember/component';

export default Component.extend({
tagName: '',

errorMessage: null,
onDismiss() {},
});
23 changes: 23 additions & 0 deletions ui/app/components/job-page/parts/title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Component from '@ember/component';

export default Component.extend({
tagName: '',

job: null,
title: null,

handleError() {},

actions: {
stopJob() {
this.get('job')
.stop()
.catch(() => {
this.get('handleError')({
title: 'Could Not Stop Job',
description: 'Your ACL token does not grant permission to stop jobs.',
});
});
},
},
});
11 changes: 7 additions & 4 deletions ui/app/components/job-page/periodic.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ import { inject as service } from '@ember/service';
export default AbstractJobPage.extend({
store: service(),

errorMessage: '',
errorMessage: null,

actions: {
forceLaunch() {
this.get('job')
.forcePeriodic()
.catch(error => {
this.set('errorMessage', `Could not force launch: ${error}`);
.catch(() => {
this.set('errorMessage', {
title: 'Could Not Force Launch',
description: 'Your ACL token does not grant permission to submit jobs.',
});
});
},
clearErrorMessage() {
this.set('errorMessage', '');
this.set('errorMessage', null);
},
},
});
26 changes: 26 additions & 0 deletions ui/app/components/two-step-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Component from '@ember/component';
import { equal } from '@ember/object/computed';

export default Component.extend({
classNames: ['two-step-button'],

idleText: '',
cancelText: '',
confirmText: '',
confirmationMessage: '',
onConfirm() {},
onCancel() {},

state: 'idle',
isIdle: equal('state', 'idle'),
isPendingConfirmation: equal('state', 'prompt'),

actions: {
setToIdle() {
this.set('state', 'idle');
},
promptForConfirmation() {
this.set('state', 'prompt');
},
},
});
4 changes: 4 additions & 0 deletions ui/app/models/job.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ export default Model.extend({
return this.store.adapterFor('job').forcePeriodic(this);
},

stop() {
return this.store.adapterFor('job').stop(this);
},

statusClass: computed('status', function() {
const classMap = {
pending: 'is-pending',
Expand Down
37 changes: 19 additions & 18 deletions ui/app/styles/components.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
@import "./components/badge";
@import "./components/boxed-section";
@import "./components/cli-window";
@import "./components/ember-power-select";
@import "./components/empty-message";
@import "./components/error-container";
@import "./components/gutter";
@import "./components/inline-definitions";
@import "./components/job-diff";
@import "./components/json-viewer";
@import "./components/loading-spinner";
@import "./components/metrics";
@import "./components/node-status-light";
@import "./components/page-layout";
@import "./components/simple-list";
@import "./components/status-text";
@import "./components/timeline";
@import "./components/tooltip";
@import './components/badge';
@import './components/boxed-section';
@import './components/cli-window';
@import './components/ember-power-select';
@import './components/empty-message';
@import './components/error-container';
@import './components/gutter';
@import './components/inline-definitions';
@import './components/job-diff';
@import './components/json-viewer';
@import './components/loading-spinner';
@import './components/metrics';
@import './components/node-status-light';
@import './components/page-layout';
@import './components/simple-list';
@import './components/status-text';
@import './components/timeline';
@import './components/tooltip';
@import './components/two-step-button';
14 changes: 14 additions & 0 deletions ui/app/styles/components/two-step-button.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.two-step-button {
display: inline;
position: relative;

.confirmation-text {
position: absolute;
left: 0;
top: -1.2em;
font-size: $body-size;
font-weight: $weight-normal;
color: darken($grey-blue, 20%);
white-space: nowrap;
}
}
7 changes: 3 additions & 4 deletions ui/app/templates/components/job-page/batch.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
<h1 class="title">
{{job.name}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
</h1>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{job-page/parts/title job=job handleError=(action "handleError")}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
7 changes: 3 additions & 4 deletions ui/app/templates/components/job-page/parameterized-child.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
<h1 class="title">
{{job.trimmedName}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
</h1>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{job-page/parts/title job=job title=job.trimmedName handleError=(action "handleError")}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
8 changes: 4 additions & 4 deletions ui/app/templates/components/job-page/parameterized.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
<h1 class="title">
{{job.name}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{#job-page/parts/title job=job handleError=(action "handleError")}}
<span class="tag is-hollow">Parameterized</span>
</h1>
{{/job-page/parts/title}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
13 changes: 13 additions & 0 deletions ui/app/templates/components/job-page/parts/error.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{#if errorMessage}}
<div class="notification is-danger">
<div class="columns">
<div class="column">
<h3 data-test-job-error-title class="title is-4">{{errorMessage.title}}</h3>
<p data-test-job-error-body>{{errorMessage.description}}</p>
</div>
<div class="column is-centered is-minimum">
<button data-test-job-error-close class="button is-danger" onclick={{action onDismiss}}>Okay</button>
</div>
</div>
</div>
{{/if}}
14 changes: 14 additions & 0 deletions ui/app/templates/components/job-page/parts/title.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<h1 class="title">
{{or title job.name}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
{{yield}}
{{#if (not (eq job.status "dead"))}}
{{two-step-button
data-test-stop
idleText="Stop"
cancelText="Cancel"
confirmText="Yes, Stop"
confirmationMessage="Are you sure you want to stop this job?"
onConfirm=(action "stopJob")}}
{{/if}}
</h1>
7 changes: 3 additions & 4 deletions ui/app/templates/components/job-page/periodic-child.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
<h1 class="title">
{{job.trimmedName}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
</h1>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{job-page/parts/title job=job title=job.trimmedName handleError=(action "handleError")}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
21 changes: 4 additions & 17 deletions ui/app/templates/components/job-page/periodic.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,12 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
{{#if errorMessage}}
<div class="notification is-danger">
<div class="columns">
<div class="column">
<h3 data-test-force-error-title class="title is-4">Could Not Force Launch</h3>
<p data-test-force-error-body>Your ACL token does not grant permission to submit jobs.</p>
</div>
<div class="column is-centered is-minimum">
<button data-test-force-error-close class="button is-danger" {{action "clearErrorMessage"}}>Okay</button>
</div>
</div>
</div>
{{/if}}
<h1 class="title">
{{job.name}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{#job-page/parts/title job=job title=job.trimmedName handleError=(action "handleError")}}
<span class="tag is-hollow">periodic</span>
<button data-test-force-launch class="button is-warning is-small is-inline" onclick={{action "forceLaunch"}}>Force Launch</button>
</h1>
{{/job-page/parts/title}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
7 changes: 3 additions & 4 deletions ui/app/templates/components/job-page/service.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
<h1 class="title">
{{job.name}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
</h1>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{job-page/parts/title job=job handleError=(action "handleError")}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
7 changes: 3 additions & 4 deletions ui/app/templates/components/job-page/system.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
{{/each}}
{{/global-header}}
{{#job-page/parts/body job=job onNamespaceChange=onNamespaceChange}}
<h1 class="title">
{{job.name}}
<span class="bumper-left tag {{job.statusClass}}" data-test-job-status>{{job.status}}</span>
</h1>
{{job-page/parts/error errorMessage=errorMessage onDismiss=(action "clearErrorMessage")}}

{{job-page/parts/title job=job handleError=(action "handleError")}}

<div class="boxed-section job-stats">
<div class="boxed-section-body">
Expand Down
19 changes: 19 additions & 0 deletions ui/app/templates/components/two-step-button.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{#if isIdle}}
<button data-test-idle-button type="button" class="button is-warning is-small is-inline" onclick={{action "promptForConfirmation"}}>
{{idleText}}
</button>
{{else if isPendingConfirmation}}
<span data-test-confirmation-message class="confirmation-text">{{confirmationMessage}}</span>
<button data-test-cancel-button type="button" class="button is-dark is-outlined is-small is-inline" onclick={{action (queue
(action "setToIdle")
(action onCancel)
)}}>
{{cancelText}}
</button>
<button data-test-confirm-button class="button is-danger is-small is-inline" onclick={{action (queue
(action "setToIdle")
(action onConfirm)
)}}>
{{confirmText}}
</button>
{{/if}}
6 changes: 6 additions & 0 deletions ui/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ export default function() {
return new Response(200, {}, '{}');
});

this.delete('/job/:id', function(schema, { params }) {
const job = schema.jobs.find(params.id);
job.update({ status: 'dead' });
return new Response(204, {}, '');
});

this.get('/deployment/:id');

this.get('/job/:id/evaluations', function({ evaluations }, { params }) {
Expand Down
Loading

0 comments on commit fb7e0c1

Please sign in to comment.