[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:
Phil Renaud 2023-03-20 09:24:39 -04:00 committed by GitHub
parent 47be374bbd
commit ccce4b68f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 11 deletions

3
.changelog/16378.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
ui: added new keyboard commands for job start, stop, exec, and client metadata
```

View File

@ -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',

View File

@ -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');
}
}

View File

@ -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();
}
});

View File

@ -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>

View File

@ -5,7 +5,12 @@
class="button exec-button is-outline is-small {{if cannotExec "tooltip"}}"
disabled={{if cannotExec 'disabled'}}
aria-label={{if cannotExec "You dont 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>

View File

@ -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>

View File

@ -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>