mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 17:35:43 +03:00
Error messages for job submit
This commit is contained in:
@@ -1,46 +1,61 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { computed } from '@ember/object';
|
||||
import { task } from 'ember-concurrency';
|
||||
import { qpBuilder } from 'nomad-ui/utils/classes/query-params';
|
||||
import { next } from '@ember/runloop';
|
||||
import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
|
||||
import localStorageProperty from 'nomad-ui/utils/properties/local-storage';
|
||||
|
||||
export default Controller.extend({
|
||||
parseError: null,
|
||||
planError: null,
|
||||
runError: null,
|
||||
|
||||
showPlanMessage: localStorageProperty('nomadMessageJobPlan', true),
|
||||
showEditorMessage: localStorageProperty('nomadMessageJobEditor', true),
|
||||
|
||||
stage: computed('planOutput', function() {
|
||||
return this.get('planOutput') ? 'plan' : 'editor';
|
||||
}),
|
||||
|
||||
plan: task(function*() {
|
||||
this.cancel();
|
||||
this.reset();
|
||||
|
||||
try {
|
||||
yield this.get('model').parse();
|
||||
} catch (err) {
|
||||
this.set('parseError', err);
|
||||
const error = messageFromAdapterError(err) || 'Could not parse input';
|
||||
this.set('parseError', error);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const planOutput = yield this.get('model').plan();
|
||||
this.set('planOutput', planOutput);
|
||||
} catch (err) {
|
||||
this.set('planError', err);
|
||||
const error = messageFromAdapterError(err) || 'Could not plan job';
|
||||
this.set('planError', error);
|
||||
}
|
||||
}).drop(),
|
||||
|
||||
submit: task(function*() {
|
||||
try {
|
||||
yield this.get('model').run();
|
||||
|
||||
const id = this.get('model.plainId');
|
||||
const namespace = this.get('model.namespace.name') || 'default';
|
||||
|
||||
this.reset();
|
||||
|
||||
// navigate to the new job page
|
||||
this.transitionToRoute('jobs.job', id, {
|
||||
queryParams: { jobNamespace: namespace },
|
||||
});
|
||||
} catch (err) {
|
||||
this.set('runError', err);
|
||||
const error = messageFromAdapterError(err) || 'Could not submit job';
|
||||
this.set('runError', error);
|
||||
}
|
||||
}),
|
||||
|
||||
cancel() {
|
||||
reset() {
|
||||
this.set('planOutput', null);
|
||||
this.set('planError', null);
|
||||
this.set('parseError', null);
|
||||
|
||||
@@ -1,16 +1,37 @@
|
||||
<section class="section">
|
||||
{{#if parseError}}
|
||||
<div data-test-parse-error class="notification is-danger">
|
||||
<h3 class="title is-4">Parse Error</h3>
|
||||
<p>{{parseError}}</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if planError}}
|
||||
<div data-test-plan-error class="notification is-danger">
|
||||
<h3 class="title is-4">Plan Error</h3>
|
||||
<p>{{planError}}</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if runError}}
|
||||
<div data-test-run-error class="notification is-danger">
|
||||
<h3 class="title is-4">Run Error</h3>
|
||||
<p>{{runError}}</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if (eq stage "editor")}}
|
||||
<div class="notification is-info">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3 class="title is-4">Run a Job</h3>
|
||||
<p>Paste or author HCL or JSON to submit to your cluster. A plan will be requested before the job is submitted.</p>
|
||||
</div>
|
||||
<div class="column is-centered is-minimum">
|
||||
<button class="button is-info">Okay</button>
|
||||
{{#if showEditorMessage}}
|
||||
<div class="notification is-info">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3 class="title is-4">Run a Job</h3>
|
||||
<p>Paste or author HCL or JSON to submit to your cluster. A plan will be requested before the job is submitted.</p>
|
||||
</div>
|
||||
<div class="column is-centered is-minimum">
|
||||
<button class="button is-info" onclick={{toggle-action "showEditorMessage" this}}>Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="boxed-section">
|
||||
<div class="boxed-section-head">
|
||||
Job Definition
|
||||
@@ -33,17 +54,19 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if (eq stage "plan")}}
|
||||
<div class="notification is-info">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3 class="title is-4">Job Plan</h3>
|
||||
<p>This is the impact running this job will have on your cluster.</p>
|
||||
</div>
|
||||
<div class="column is-centered is-minimum">
|
||||
<button class="button is-info">Okay</button>
|
||||
{{#if showPlanMessage}}
|
||||
<div class="notification is-info">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h3 class="title is-4">Job Plan</h3>
|
||||
<p>This is the impact running this job will have on your cluster.</p>
|
||||
</div>
|
||||
<div class="column is-centered is-minimum">
|
||||
<button class="button is-info" onclick={{toggle-action "showPlanMessage" this}}>Okay</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="boxed-section">
|
||||
<div class="boxed-section-head">Job Plan</div>
|
||||
<div class="boxed-section-body is-dark">
|
||||
@@ -52,7 +75,7 @@
|
||||
</div>
|
||||
<div class="content is-associative">
|
||||
<button class="button is-primary {{if submit.isRunning "is-loading"}}" onclick={{perform submit}}>Submit</button>
|
||||
<button class="button is-light" onclick={{action cancel}}>Cancel</button>
|
||||
<button class="button is-light" onclick={{action reset}}>Cancel</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
6
ui/app/utils/message-from-adapter-error.js
Normal file
6
ui/app/utils/message-from-adapter-error.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// Returns a single string based on the response the adapter received
|
||||
export default function messageFromAdapterError(error) {
|
||||
if (error.errors) {
|
||||
return error.errors.mapBy('detail').join('\n\n');
|
||||
}
|
||||
}
|
||||
19
ui/app/utils/properties/local-storage.js
Normal file
19
ui/app/utils/properties/local-storage.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { computed } from '@ember/object';
|
||||
|
||||
// An Ember.Computed property that persists set values in localStorage
|
||||
// and will attempt to get its initial value from localStorage before
|
||||
// falling back to a default.
|
||||
//
|
||||
// ex. showTutorial: localStorageProperty('nomadTutorial', true),
|
||||
export default function localStorageProperty(localStorageKey, defaultValue) {
|
||||
return computed({
|
||||
get() {
|
||||
const persistedValue = window.localStorage.getItem(localStorageKey);
|
||||
return persistedValue ? JSON.parse(persistedValue) : defaultValue;
|
||||
},
|
||||
set(key, value) {
|
||||
window.localStorage.setItem(localStorageKey, JSON.stringify(value));
|
||||
return value;
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user