[ui] Perform common job tasks with keyboard shortcuts (#16378)
* Throw your mouse into traffic * Add node metadata with a shortcut * Re-labelled * Adds a toast notification to job start/stop on keyboard shortcut * Typo fix
This commit is contained in:
parent
47be374bbd
commit
ccce4b68f2
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
ui: added new keyboard commands for job start, stop, exec, and client metadata
|
||||
```
|
|
@ -1,3 +1,4 @@
|
|||
// @ts-check
|
||||
import Component from '@ember/component';
|
||||
import { task } from 'ember-concurrency';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
@ -16,12 +17,22 @@ export default class Title extends Component {
|
|||
|
||||
handleError() {}
|
||||
|
||||
@task(function* () {
|
||||
/**
|
||||
* @param {boolean} withNotifications - Whether to show a toast on success, as when triggered by keyboard shortcut
|
||||
*/
|
||||
@task(function* (withNotifications = false) {
|
||||
try {
|
||||
const job = this.job;
|
||||
yield job.stop();
|
||||
// Eagerly update the job status to avoid flickering
|
||||
this.job.set('status', 'dead');
|
||||
job.set('status', 'dead');
|
||||
if (withNotifications) {
|
||||
this.notifications.add({
|
||||
title: 'Job Stopped',
|
||||
message: `${job.name} has been stopped`,
|
||||
color: 'success',
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.handleError({
|
||||
title: 'Could Not Stop Job',
|
||||
|
@ -37,7 +48,7 @@ export default class Title extends Component {
|
|||
yield job.purge();
|
||||
this.notifications.add({
|
||||
title: 'Job Purged',
|
||||
message: `You have purged ${this.job.name}`,
|
||||
message: `You have purged ${job.name}`,
|
||||
color: 'success',
|
||||
});
|
||||
this.router.transitionTo('jobs');
|
||||
|
@ -50,7 +61,10 @@ export default class Title extends Component {
|
|||
})
|
||||
purgeJob;
|
||||
|
||||
@task(function* () {
|
||||
/**
|
||||
* @param {boolean} withNotifications - Whether to show a toast on success, as when triggered by keyboard shortcut
|
||||
*/
|
||||
@task(function* (withNotifications = false) {
|
||||
const job = this.job;
|
||||
const definition = yield job.fetchRawDefinition();
|
||||
|
||||
|
@ -62,6 +76,13 @@ export default class Title extends Component {
|
|||
yield job.update();
|
||||
// Eagerly update the job status to avoid flickering
|
||||
job.set('status', 'running');
|
||||
if (withNotifications) {
|
||||
this.notifications.add({
|
||||
title: 'Job Started',
|
||||
message: `${job.name} has started`,
|
||||
color: 'success',
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.handleError({
|
||||
title: 'Could Not Start Job',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import { alias, readOnly } from '@ember/object/computed';
|
||||
import Controller from '@ember/controller';
|
||||
import { computed } from '@ember/object';
|
||||
import { computed, action } from '@ember/object';
|
||||
import { scheduleOnce } from '@ember/runloop';
|
||||
import intersection from 'lodash.intersection';
|
||||
import Sortable from 'nomad-ui/mixins/sortable';
|
||||
|
@ -20,6 +20,7 @@ export default class IndexController extends Controller.extend(
|
|||
) {
|
||||
@service system;
|
||||
@service userSettings;
|
||||
@service router;
|
||||
|
||||
isForbidden = false;
|
||||
|
||||
|
@ -254,4 +255,9 @@ export default class IndexController extends Controller.extend(
|
|||
setFacetQueryParam(queryParam, selection) {
|
||||
this.set(queryParam, serialize(selection));
|
||||
}
|
||||
|
||||
@action
|
||||
goToRun() {
|
||||
this.router.transitionTo('jobs.run');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -342,7 +342,7 @@ export default class KeyboardService extends Service {
|
|||
this.displayHints = true;
|
||||
} else {
|
||||
if (!DISALLOWED_KEYS.includes(key)) {
|
||||
this.addKeyToBuffer.perform(key, shifted);
|
||||
this.addKeyToBuffer.perform(key, shifted, event);
|
||||
}
|
||||
}
|
||||
} else if (type === 'release') {
|
||||
|
@ -382,7 +382,7 @@ export default class KeyboardService extends Service {
|
|||
* @param {string} key
|
||||
* @param {boolean} shifted
|
||||
*/
|
||||
@restartableTask *addKeyToBuffer(key, shifted) {
|
||||
@restartableTask *addKeyToBuffer(key, shifted, event) {
|
||||
// Replace key with its unshifted equivalent if it's a number key
|
||||
if (shifted && key in DIGIT_MAP) {
|
||||
key = DIGIT_MAP[key];
|
||||
|
@ -411,6 +411,7 @@ export default class KeyboardService extends Service {
|
|||
command.label === 'Show Keyboard Shortcuts' ||
|
||||
command.label === 'Hide Keyboard Shortcuts'
|
||||
) {
|
||||
event.preventDefault();
|
||||
command.action();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -879,6 +879,11 @@
|
|||
type="button"
|
||||
class="button is-primary"
|
||||
{{on "click" (action (mut this.editingMetadata) true)}}
|
||||
{{keyboard-shortcut
|
||||
label="Add Dynamic Node Metadata"
|
||||
pattern=(array "m" "e" "t" "a")
|
||||
action=(action (mut this.editingMetadata) true)
|
||||
}}
|
||||
>
|
||||
Add new Dynamic Metadata
|
||||
</button>
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
class="button exec-button is-outline is-small {{if cannotExec "tooltip"}}"
|
||||
disabled={{if cannotExec 'disabled'}}
|
||||
aria-label={{if cannotExec "You don’t have permission to exec"}}
|
||||
{{action "open"}}>
|
||||
{{action "open"}}
|
||||
{{keyboard-shortcut
|
||||
label="Exec"
|
||||
pattern=(array "e" "x" "e" "c")
|
||||
action=(action "open")
|
||||
}}>
|
||||
{{x-icon "console"}}
|
||||
<span>Exec</span>
|
||||
</button>
|
||||
|
|
|
@ -23,7 +23,12 @@
|
|||
@confirmText="Yes, Stop Job"
|
||||
@confirmationMessage="Are you sure you want to stop this job?"
|
||||
@awaitingConfirmation={{this.stopJob.isRunning}}
|
||||
@onConfirm={{perform this.stopJob}} />
|
||||
@onConfirm={{perform this.stopJob}}
|
||||
{{keyboard-shortcut
|
||||
label="Stop"
|
||||
pattern=(array "s" "t" "o" "p")
|
||||
action=(perform this.stopJob true)
|
||||
}} />
|
||||
{{else}}
|
||||
<TwoStepButton
|
||||
data-test-purge
|
||||
|
@ -33,7 +38,13 @@
|
|||
@confirmText="Yes, Purge Job"
|
||||
@confirmationMessage="Are you sure? You cannot undo this action."
|
||||
@awaitingConfirmation={{this.purgeJob.isRunning}}
|
||||
@onConfirm={{perform this.purgeJob}} />
|
||||
@onConfirm={{perform this.purgeJob}}
|
||||
{{keyboard-shortcut
|
||||
label="Purge"
|
||||
pattern=(array "p" "u" "r" "g" "e")
|
||||
action=(perform this.purgeJob)
|
||||
}}
|
||||
/>
|
||||
<TwoStepButton
|
||||
data-test-start
|
||||
@alignRight={{true}}
|
||||
|
@ -42,7 +53,13 @@
|
|||
@confirmText="Yes, Start Job"
|
||||
@confirmationMessage="Are you sure you want to start this job?"
|
||||
@awaitingConfirmation={{this.startJob.isRunning}}
|
||||
@onConfirm={{perform this.startJob}} />
|
||||
@onConfirm={{perform this.startJob}}
|
||||
{{keyboard-shortcut
|
||||
label="Start"
|
||||
pattern=(array "s" "t" "a" "r" "t")
|
||||
action=(perform this.startJob true)
|
||||
}}
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
</h1>
|
||||
|
|
|
@ -84,6 +84,11 @@
|
|||
@query={{hash namespace=this.qpNamespace}}
|
||||
data-test-run-job
|
||||
class="button is-primary"
|
||||
{{keyboard-shortcut
|
||||
label="Run Job"
|
||||
pattern=(array "r" "u" "n")
|
||||
action=(action this.goToRun)
|
||||
}}
|
||||
>
|
||||
Run Job
|
||||
</LinkTo>
|
||||
|
|
Loading…
Reference in New Issue