From bb323ef3de2201a17d1d9d05f5cba90dbb06d40e Mon Sep 17 00:00:00 2001 From: Luiz Aoqui Date: Thu, 26 Jan 2023 16:03:07 -0500 Subject: [PATCH] ui: fix navigation for namespaced jobs in search and job version (#15906) --- .changelog/15906.txt | 3 ++ ui/app/components/global-search/control.js | 15 +++++++--- ui/app/components/gutter-menu.js | 16 ----------- ui/app/components/job-version.js | 5 +--- ui/tests/acceptance/job-versions-test.js | 2 +- ui/tests/acceptance/search-test.js | 32 +++++++++++++++++++--- 6 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 .changelog/15906.txt diff --git a/.changelog/15906.txt b/.changelog/15906.txt new file mode 100644 index 000000000..0c330a76b --- /dev/null +++ b/.changelog/15906.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: Fix navigation to pages for jobs that are not in the default namespace +``` diff --git a/ui/app/components/global-search/control.js b/ui/app/components/global-search/control.js index b3d8a9230..fca5ee233 100644 --- a/ui/app/components/global-search/control.js +++ b/ui/app/components/global-search/control.js @@ -13,6 +13,7 @@ const MAXIMUM_RESULTS = 10; export default class GlobalSearchControl extends Component { @service router; @service token; + @service store; searchString = null; @@ -180,14 +181,20 @@ export default class GlobalSearchControl extends Component { @action selectOption(model) { if (model.type === 'job') { - this.router.transitionTo('jobs.job', model.id, { - queryParams: { namespace: model.namespace }, + const fullId = JSON.stringify([model.id, model.namespace]); + this.store.findRecord('job', fullId).then((job) => { + this.router.transitionTo('jobs.job', job.idWithNamespace); }); } else if (model.type === 'node') { this.router.transitionTo('clients.client', model.id); } else if (model.type === 'task-group') { - this.router.transitionTo('jobs.job.task-group', model.jobId, model.id, { - queryParams: { namespace: model.namespace }, + const fullJobId = JSON.stringify([model.jobId, model.namespace]); + this.store.findRecord('job', fullJobId).then((job) => { + this.router.transitionTo( + 'jobs.job.task-group', + job.idWithNamespace, + model.id + ); }); } else if (model.type === 'plugin') { this.router.transitionTo('csi.plugins.plugin', model.id); diff --git a/ui/app/components/gutter-menu.js b/ui/app/components/gutter-menu.js index c84a4d0e4..000329b36 100644 --- a/ui/app/components/gutter-menu.js +++ b/ui/app/components/gutter-menu.js @@ -42,20 +42,4 @@ export default class GutterMenu extends Component { transitionTo(destination) { return this.router.transitionTo(destination); } - - gotoJobsForNamespace(namespace) { - if (!namespace || !namespace.get('id')) return; - - // Jobs and CSI Volumes are both namespace-sensitive. Changing namespaces is - // an intent to reset context, but where to reset to depends on where the namespace - // is being switched from. Jobs take precedence, but if the namespace is switched from - // a storage-related page, context should be reset to volumes. - const destination = this.router.currentRouteName.startsWith('csi.') - ? 'csi.volumes' - : 'jobs'; - - this.router.transitionTo(destination, { - queryParams: { namespace: namespace.get('id') }, - }); - } } diff --git a/ui/app/components/job-version.js b/ui/app/components/job-version.js index 3e5ad74af..7aaff6c97 100644 --- a/ui/app/components/job-version.js +++ b/ui/app/components/job-version.js @@ -65,10 +65,7 @@ export default class JobVersion extends Component { }); } else { const job = this.get('version.job'); - - this.router.transitionTo('jobs.job', job.get('plainId'), { - queryParams: { namespace: job.get('namespace.name') }, - }); + this.router.transitionTo('jobs.job.index', job.get('idWithNamespace')); } } catch (e) { this.handleError({ diff --git a/ui/tests/acceptance/job-versions-test.js b/ui/tests/acceptance/job-versions-test.js index 596c5df88..fdf432fe2 100644 --- a/ui/tests/acceptance/job-versions-test.js +++ b/ui/tests/acceptance/job-versions-test.js @@ -93,7 +93,7 @@ module('Acceptance | job versions', function (hooks) { JobVersion: versionNumberRevertingTo, }); - assert.equal(currentURL(), `/jobs/${job.id}?namespace=${namespace.id}`); + assert.equal(currentURL(), `/jobs/${job.id}@${namespace.id}`); } }); diff --git a/ui/tests/acceptance/search-test.js b/ui/tests/acceptance/search-test.js index 78a0fbd2b..32d01d324 100644 --- a/ui/tests/acceptance/search-test.js +++ b/ui/tests/acceptance/search-test.js @@ -17,6 +17,9 @@ module('Acceptance | search', function (hooks) { server.create('node', { name: 'xyz' }); const otherNode = server.create('node', { name: 'ghi' }); + server.create('namespace'); + server.create('namespace', { id: 'dev' }); + server.create('job', { id: 'vwxyz', namespaceId: 'default', @@ -30,6 +33,13 @@ module('Acceptance | search', function (hooks) { groupsCount: 1, groupTaskCount: 1, }); + server.create('job', { + id: 'xyzw', + name: 'xyzw job', + namespaceId: 'dev', + groupsCount: 1, + groupTaskCount: 1, + }); server.create('job', { id: 'abc', namespaceId: 'default', @@ -39,6 +49,7 @@ module('Acceptance | search', function (hooks) { const firstAllocation = server.schema.allocations.all().models[0]; const firstTaskGroup = server.schema.taskGroups.all().models[0]; + const namespacedTaskGroup = server.schema.taskGroups.all().models[2]; server.create('csi-plugin', { id: 'xyz-plugin', createVolumes: false }); @@ -50,10 +61,11 @@ module('Acceptance | search', function (hooks) { assert.equal(search.groups.length, 5); search.groups[0].as((jobs) => { - assert.equal(jobs.name, 'Jobs (2)'); - assert.equal(jobs.options.length, 2); + assert.equal(jobs.name, 'Jobs (3)'); + assert.equal(jobs.options.length, 3); assert.equal(jobs.options[0].text, 'default > vwxyz'); assert.equal(jobs.options[1].text, 'default > xyz job'); + assert.equal(jobs.options[2].text, 'dev > xyzw job'); }); search.groups[1].as((clients) => { @@ -80,7 +92,11 @@ module('Acceptance | search', function (hooks) { }); await Layout.navbar.search.groups[0].options[1].click(); - assert.equal(currentURL(), '/jobs/xyz'); + assert.equal(currentURL(), '/jobs/xyz@default'); + + await selectSearch(Layout.navbar.search.scope, 'xy'); + await Layout.navbar.search.groups[0].options[2].click(); + assert.equal(currentURL(), '/jobs/xyzw@dev'); await selectSearch(Layout.navbar.search.scope, otherNode.name); await Layout.navbar.search.groups[1].options[0].click(); @@ -100,7 +116,15 @@ module('Acceptance | search', function (hooks) { `default > vwxyz > ${firstTaskGroup.name}` ); await Layout.navbar.search.groups[3].options[0].click(); - assert.equal(currentURL(), `/jobs/vwxyz/${firstTaskGroup.name}`); + assert.equal(currentURL(), `/jobs/vwxyz@default/${firstTaskGroup.name}`); + + await selectSearch(Layout.navbar.search.scope, namespacedTaskGroup.name); + assert.equal( + Layout.navbar.search.groups[3].options[0].text, + `dev > xyzw > ${namespacedTaskGroup.name}` + ); + await Layout.navbar.search.groups[3].options[0].click(); + assert.equal(currentURL(), `/jobs/xyzw@dev/${namespacedTaskGroup.name}`); await selectSearch(Layout.navbar.search.scope, 'xy'); await Layout.navbar.search.groups[4].options[0].click();