diff --git a/ui/app/components/breadcrumbs/default.hbs b/ui/app/components/breadcrumbs/default.hbs
new file mode 100644
index 000000000000..8b5108a7da69
--- /dev/null
+++ b/ui/app/components/breadcrumbs/default.hbs
@@ -0,0 +1,5 @@
+
+
+ {{@crumb.label}}
+
+
\ No newline at end of file
diff --git a/ui/app/components/breadcrumbs/job.hbs b/ui/app/components/breadcrumbs/job.hbs
new file mode 100644
index 000000000000..140ee8b9a94f
--- /dev/null
+++ b/ui/app/components/breadcrumbs/job.hbs
@@ -0,0 +1,19 @@
+
+ {{did-insert trigger.fns.do}}
+ {{#if trigger.data.result}}
+
+
+ {{trigger.data.result.label}}
+
+
+ {{/if}}
+
+
+ {{this.crumb.label}}
+
+
+
\ No newline at end of file
diff --git a/ui/app/components/breadcrumbs/job.js b/ui/app/components/breadcrumbs/job.js
new file mode 100644
index 000000000000..f58ef5677c1e
--- /dev/null
+++ b/ui/app/components/breadcrumbs/job.js
@@ -0,0 +1,36 @@
+import { action } from '@ember/object';
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { qpBuilder } from 'nomad-ui/utils/classes/query-params';
+
+export default class BreadcrumbsJob extends Component {
+ get job() {
+ return this.args.crumb.job;
+ }
+
+ @tracked parent = null;
+
+ generateCrumb(job) {
+ return {
+ label: job.get('trimmedName') || job.trimmedName,
+ args: [
+ 'jobs.job.index',
+ job.get('plainId') || job.plainId,
+ qpBuilder({
+ jobNamespace: job.get('namespace.name') || 'default',
+ }),
+ ],
+ };
+ }
+
+ get crumb() {
+ if (!this.job) return null;
+ return this.generateCrumb(this.job);
+ }
+
+ @action
+ fetchParent() {
+ this.parent = this.job.parent || this.job.get('parent');
+ return this.generateCrumb(this.parent);
+ }
+}
diff --git a/ui/app/components/trigger.hbs b/ui/app/components/trigger.hbs
new file mode 100644
index 000000000000..c6fdb221f2a9
--- /dev/null
+++ b/ui/app/components/trigger.hbs
@@ -0,0 +1 @@
+{{yield (hash data=this.data fns=this.fns)}}
\ No newline at end of file
diff --git a/ui/app/components/trigger.js b/ui/app/components/trigger.js
new file mode 100644
index 000000000000..8054060e14cf
--- /dev/null
+++ b/ui/app/components/trigger.js
@@ -0,0 +1,62 @@
+import { action } from '@ember/object';
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { task } from 'ember-concurrency';
+
+const noOp = () => undefined;
+
+export default class Trigger extends Component {
+ @tracked error = null;
+ @tracked result = null;
+
+ get isBusy() {
+ return this.triggerTask.isRunning;
+ }
+
+ get isIdle() {
+ return this.triggerTask.isIdle;
+ }
+
+ get isSuccess() {
+ return this.triggerTask.last.isSuccessful;
+ }
+
+ get isError() {
+ return this.triggerTask.lastErrored;
+ }
+
+ get fns() {
+ return {
+ do: this.onTrigger,
+ };
+ }
+
+ get onError() {
+ return this.args.onError ?? noOp;
+ }
+
+ get onSuccess() {
+ return this.args.onSuccess ?? noOp;
+ }
+
+ get data() {
+ const { isBusy, isIdle, isSuccess, isError, result } = this;
+ return { isBusy, isIdle, isSuccess, isError, result };
+ }
+
+ @task(function*() {
+ try {
+ this.result = yield this.args.do();
+ this.onSuccess(this.result);
+ } catch (e) {
+ this.error = e;
+ this.onError(this.error);
+ }
+ })
+ triggerTask;
+
+ @action
+ onTrigger() {
+ this.triggerTask.perform();
+ }
+}
diff --git a/ui/app/controllers/allocations/allocation.js b/ui/app/controllers/allocations/allocation.js
index fbd071ddd0ed..2491bfd290c4 100644
--- a/ui/app/controllers/allocations/allocation.js
+++ b/ui/app/controllers/allocations/allocation.js
@@ -1,6 +1,5 @@
import Controller from '@ember/controller';
import { qpBuilder } from 'nomad-ui/utils/classes/query-params';
-import { jobCrumbs } from 'nomad-ui/utils/breadcrumb-utils';
export default class AllocationsAllocationController extends Controller {
// Allocation breadcrumbs extend from job / task group breadcrumbs
@@ -13,7 +12,7 @@ export default class AllocationsAllocationController extends Controller {
return [
{ label: 'Jobs', args: ['jobs.index', jobQueryParams] },
- ...jobCrumbs(model.get('job')),
+ { type: 'job', job: model.get('job') },
{
label: model.get('taskGroupName'),
args: [
diff --git a/ui/app/controllers/clients/client.js b/ui/app/controllers/clients/client.js
index 3efd6ebe1a56..aa558c80b0bb 100644
--- a/ui/app/controllers/clients/client.js
+++ b/ui/app/controllers/clients/client.js
@@ -1,7 +1,7 @@
import Controller from '@ember/controller';
export default class ClientsClientController extends Controller {
- breadcrumbs() {
+ get breadcrumbs() {
const model = this.model;
if (!model) return [];
return [
diff --git a/ui/app/controllers/jobs/job.js b/ui/app/controllers/jobs/job.js
index f369e82b4717..17e726db4910 100644
--- a/ui/app/controllers/jobs/job.js
+++ b/ui/app/controllers/jobs/job.js
@@ -1,5 +1,4 @@
import Controller from '@ember/controller';
-import { jobCrumbs } from 'nomad-ui/utils/breadcrumb-utils';
export default class JobController extends Controller {
queryParams = [
@@ -9,5 +8,7 @@ export default class JobController extends Controller {
];
jobNamespace = 'default';
- breadcrumbs = jobCrumbs(this.model);
+ get breadcrumbs() {
+ return [{ type: 'job', job: this.model }];
+ }
}
diff --git a/ui/app/templates/components/app-breadcrumbs.hbs b/ui/app/templates/components/app-breadcrumbs.hbs
index 3a24a6f9a78f..618237f31b7a 100644
--- a/ui/app/templates/components/app-breadcrumbs.hbs
+++ b/ui/app/templates/components/app-breadcrumbs.hbs
@@ -1,17 +1,15 @@
{{#each bb as |breadcrumb index|}}
{{#each breadcrumb.args.crumb as |b|}}
-
- {{#if b.isPending}}
+ {{#if b.isPending}}
+
…
- {{else}}
-
- {{b.label}}
-
- {{/if}}
-
+
+ {{else}}
+ {{component (concat "breadcrumbs/" (or b.type "default")) crumb=b}}
+ {{/if}}
{{/each}}
{{/each}}
\ No newline at end of file
diff --git a/ui/app/templates/components/job-page/parts/summary.hbs b/ui/app/templates/components/job-page/parts/summary.hbs
index e31d7a125dff..ebd75dc568d7 100644
--- a/ui/app/templates/components/job-page/parts/summary.hbs
+++ b/ui/app/templates/components/job-page/parts/summary.hbs
@@ -61,5 +61,4 @@
{{/component}}
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ui/app/templates/jobs.hbs b/ui/app/templates/jobs.hbs
index 6e448d265b6c..44a687f0c474 100644
--- a/ui/app/templates/jobs.hbs
+++ b/ui/app/templates/jobs.hbs
@@ -1,4 +1,4 @@
+
{{outlet}}
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/ui/app/templates/servers/server.hbs b/ui/app/templates/servers/server.hbs
index c24cd68950a9..2fd45556a2be 100644
--- a/ui/app/templates/servers/server.hbs
+++ b/ui/app/templates/servers/server.hbs
@@ -1 +1 @@
-{{outlet}}
+{{outlet}}
\ No newline at end of file
diff --git a/ui/app/utils/breadcrumb-utils.js b/ui/app/utils/breadcrumb-utils.js
deleted file mode 100644
index 5050ee0f3ed8..000000000000
--- a/ui/app/utils/breadcrumb-utils.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import PromiseObject from 'nomad-ui/utils/classes/promise-object';
-import { qpBuilder } from 'nomad-ui/utils/classes/query-params';
-
-export const jobCrumb = job => ({
- label: job.get('trimmedName'),
- args: [
- 'jobs.job.index',
- job.get('plainId'),
- qpBuilder({
- jobNamespace: job.get('namespace.name') || 'default',
- }),
- ],
-});
-
-export const jobCrumbs = job => {
- console.log('job\n\n', job);
- if (!job) return [];
-
- if (job.get('parent.content')) {
- return [
- PromiseObject.create({
- promise: job.get('parent').then(parent => jobCrumb(parent)),
- }),
- jobCrumb(job),
- ];
- } else {
- return [jobCrumb(job)];
- }
-};
diff --git a/ui/config/environment.js b/ui/config/environment.js
index f6944b1f883e..8357296ac023 100644
--- a/ui/config/environment.js
+++ b/ui/config/environment.js
@@ -26,7 +26,7 @@ module.exports = function(environment) {
APP: {
blockingQueries: true,
// TODO: revert before merging to main.
- mirageScenario: 'smallCluster', // convert to 'sysbatchSmall' when working on feature
+ mirageScenario: 'allJobTypes', // convert to 'sysbatchSmall' when working on feature
mirageWithNamespaces: false,
mirageWithTokens: true,
mirageWithRegions: true,
diff --git a/ui/package.json b/ui/package.json
index cf26239bf9f7..d7b1ea15b6f9 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -94,6 +94,7 @@
"ember-power-select": "^4.1.3",
"ember-qunit": "^4.6.0",
"ember-qunit-nice-errors": "^1.2.0",
+ "ember-render-helpers": "^0.2.0",
"ember-resolver": "^8.0.0",
"ember-responsive": "^3.0.4",
"ember-sinon": "^4.0.0",
diff --git a/ui/yarn.lock b/ui/yarn.lock
index 586b7893459b..fefe48c547bc 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -4345,6 +4345,13 @@ ansi-to-html@^0.6.11, ansi-to-html@^0.6.6:
dependencies:
entities "^1.1.2"
+ansi-to-html@^0.6.15:
+ version "0.6.15"
+ resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7"
+ integrity sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==
+ dependencies:
+ entities "^2.0.0"
+
ansicolors@~0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef"
@@ -8925,6 +8932,22 @@ ember-cli-typescript@^3.0.0, ember-cli-typescript@^3.1.3, ember-cli-typescript@^
stagehand "^1.0.0"
walk-sync "^2.0.0"
+ember-cli-typescript@^4.0.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-4.2.1.tgz#54d08fc90318cc986f3ea562f93ce58a6cc4c24d"
+ integrity sha512-0iKTZ+/wH6UB/VTWKvGuXlmwiE8HSIGcxHamwNhEC5x1mN3z8RfvsFZdQWYUzIWFN2Tek0gmepGRPTwWdBYl/A==
+ dependencies:
+ ansi-to-html "^0.6.15"
+ broccoli-stew "^3.0.0"
+ debug "^4.0.0"
+ execa "^4.0.0"
+ fs-extra "^9.0.1"
+ resolve "^1.5.0"
+ rsvp "^4.8.1"
+ semver "^7.3.2"
+ stagehand "^1.0.0"
+ walk-sync "^2.2.0"
+
ember-cli-typescript@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ember-cli-typescript/-/ember-cli-typescript-4.1.0.tgz#2ff17be2e6d26b58c88b1764cb73887e7176618b"
@@ -9426,6 +9449,14 @@ ember-qunit@^4.6.0:
ember-cli-test-loader "^2.2.0"
qunit "^2.9.3"
+ember-render-helpers@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/ember-render-helpers/-/ember-render-helpers-0.2.0.tgz#5f7af8ee74ae29f85e0d156b2775edff23f6de21"
+ integrity sha512-MnqGS8BnY3GJ+n5RZVVRqCwKjfXXMr5quKyqNu1vxft8oslOJuZ1f1dOesQouD+6LwD4Y9tWRVKNw+LOqM9ocw==
+ dependencies:
+ ember-cli-babel "^7.23.0"
+ ember-cli-typescript "^4.0.0"
+
ember-resolver@^8.0.0:
version "8.0.2"
resolved "https://registry.yarnpkg.com/ember-resolver/-/ember-resolver-8.0.2.tgz#8a45a744aaf5391eb52b4cb393b3b06d2db1975c"