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"