diff --git a/.changelog/16378.txt b/.changelog/16378.txt new file mode 100644 index 000000000..c82e4b8a1 --- /dev/null +++ b/.changelog/16378.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: added new keyboard commands for job start, stop, exec, and client metadata +``` diff --git a/ui/app/components/job-page/parts/title.js b/ui/app/components/job-page/parts/title.js index 09a9bb24b..1cff99459 100644 --- a/ui/app/components/job-page/parts/title.js +++ b/ui/app/components/job-page/parts/title.js @@ -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', diff --git a/ui/app/controllers/jobs/index.js b/ui/app/controllers/jobs/index.js index d4600c65b..36b3864e5 100644 --- a/ui/app/controllers/jobs/index.js +++ b/ui/app/controllers/jobs/index.js @@ -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'); + } } diff --git a/ui/app/services/keyboard.js b/ui/app/services/keyboard.js index 5e9950bd2..5c05b30ee 100644 --- a/ui/app/services/keyboard.js +++ b/ui/app/services/keyboard.js @@ -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(); } }); diff --git a/ui/app/templates/clients/client/index.hbs b/ui/app/templates/clients/client/index.hbs index 2389ed1ec..fdf962818 100644 --- a/ui/app/templates/clients/client/index.hbs +++ b/ui/app/templates/clients/client/index.hbs @@ -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 diff --git a/ui/app/templates/components/exec/open-button.hbs b/ui/app/templates/components/exec/open-button.hbs index 00156976a..1cb4d9c9b 100644 --- a/ui/app/templates/components/exec/open-button.hbs +++ b/ui/app/templates/components/exec/open-button.hbs @@ -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"}} Exec diff --git a/ui/app/templates/components/job-page/parts/title.hbs b/ui/app/templates/components/job-page/parts/title.hbs index bfc8543b3..9d0704932 100644 --- a/ui/app/templates/components/job-page/parts/title.hbs +++ b/ui/app/templates/components/job-page/parts/title.hbs @@ -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}} + @onConfirm={{perform this.purgeJob}} + {{keyboard-shortcut + label="Purge" + pattern=(array "p" "u" "r" "g" "e") + action=(perform this.purgeJob) + }} + /> + @onConfirm={{perform this.startJob}} + {{keyboard-shortcut + label="Start" + pattern=(array "s" "t" "a" "r" "t") + action=(perform this.startJob true) + }} + /> {{/if}} diff --git a/ui/app/templates/jobs/index.hbs b/ui/app/templates/jobs/index.hbs index 3df484328..5ffc665ad 100644 --- a/ui/app/templates/jobs/index.hbs +++ b/ui/app/templates/jobs/index.hbs @@ -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