From a57193dd788214ea81fff267ff1b0ef110643b35 Mon Sep 17 00:00:00 2001 From: Jai <41024828+JBhagat841@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:13:20 -0400 Subject: [PATCH] Merge pull request #10666 from hashicorp/b-ui/search-namespaces ui: Fix fuzzy search namespace-handling --- .changelog/10666.txt | 3 + ui/app/components/global-search/control.js | 84 ++++++++++++++-------- ui/mirage/config.js | 4 +- ui/tests/acceptance/search-test.js | 57 ++++++++++++--- 4 files changed, 105 insertions(+), 43 deletions(-) create mode 100644 .changelog/10666.txt diff --git a/.changelog/10666.txt b/.changelog/10666.txt new file mode 100644 index 000000000000..2b2d74d5236f --- /dev/null +++ b/.changelog/10666.txt @@ -0,0 +1,3 @@ +```release-note:bug +ui: Add ability to search across all namespaces +``` diff --git a/ui/app/components/global-search/control.js b/ui/app/components/global-search/control.js index d61232e14a0e..8f3967cca356 100644 --- a/ui/app/components/global-search/control.js +++ b/ui/app/components/global-search/control.js @@ -46,6 +46,7 @@ export default class GlobalSearchControl extends Component { body: JSON.stringify({ Text: string, Context: 'all', + Namespace: '*', }), }); @@ -57,32 +58,40 @@ export default class GlobalSearchControl extends Component { const allTaskGroupResults = results.Matches.groups || []; const allCSIPluginResults = results.Matches.plugins || []; - const jobResults = allJobResults.slice(0, MAXIMUM_RESULTS).map(({ ID: name, Scope: [ namespace, id ]}) => ({ - type: 'job', - id, - namespace, - label: name, - })); - - const nodeResults = allNodeResults.slice(0, MAXIMUM_RESULTS).map(({ ID: name, Scope: [ id ]}) => ({ - type: 'node', - id, - label: name, - })); - - const allocationResults = allAllocationResults.slice(0, MAXIMUM_RESULTS).map(({ ID: name, Scope: [ , id ]}) => ({ - type: 'allocation', - id, - label: name, - })); - - const taskGroupResults = allTaskGroupResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id, Scope: [ namespace, jobId ]}) => ({ - type: 'task-group', - id, - namespace, - jobId, - label: id, - })); + const jobResults = allJobResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: name, Scope: [namespace, id] }) => ({ + type: 'job', + id, + namespace, + label: `${namespace} > ${name}`, + })); + + const nodeResults = allNodeResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: name, Scope: [id] }) => ({ + type: 'node', + id, + label: name, + })); + + const allocationResults = allAllocationResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: name, Scope: [namespace, id] }) => ({ + type: 'allocation', + id, + label: `${namespace} > ${name}`, + })); + + const taskGroupResults = allTaskGroupResults + .slice(0, MAXIMUM_RESULTS) + .map(({ ID: id, Scope: [namespace, jobId] }) => ({ + type: 'task-group', + id, + namespace, + jobId, + label: `${namespace} > ${jobId} > ${id}`, + })); const csiPluginResults = allCSIPluginResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id }) => ({ type: 'plugin', @@ -108,17 +117,32 @@ export default class GlobalSearchControl extends Component { options: nodeResults, }, { - groupName: resultsGroupLabel('Allocations', allocationResults, allAllocationResults, allocationsTruncated), + groupName: resultsGroupLabel( + 'Allocations', + allocationResults, + allAllocationResults, + allocationsTruncated + ), options: allocationResults, }, { - groupName: resultsGroupLabel('Task Groups', taskGroupResults, allTaskGroupResults, taskGroupsTruncated), + groupName: resultsGroupLabel( + 'Task Groups', + taskGroupResults, + allTaskGroupResults, + taskGroupsTruncated + ), options: taskGroupResults, }, { - groupName: resultsGroupLabel('CSI Plugins', csiPluginResults, allCSIPluginResults, csiPluginsTruncated), + groupName: resultsGroupLabel( + 'CSI Plugins', + csiPluginResults, + allCSIPluginResults, + csiPluginsTruncated + ), options: csiPluginResults, - } + }, ]; }) search; diff --git a/ui/mirage/config.js b/ui/mirage/config.js index 3e26e3bf2b9f..e1ce1847c154 100644 --- a/ui/mirage/config.js +++ b/ui/mirage/config.js @@ -612,7 +612,7 @@ export default function() { const transformedAllocs = matchedAllocs.models.map(alloc => ({ ID: alloc.name, - Scope: [(alloc.namespace || {}).id, alloc.id], + Scope: [alloc.namespace || 'default', alloc.id], })); const transformedGroups = matchedGroups.models.map(group => ({ @@ -622,7 +622,7 @@ export default function() { const transformedJobs = matchedJobs.models.map(job => ({ ID: job.name, - Scope: [job.namespace, job.id], + Scope: [job.namespace || 'default', job.id], })); const transformedNodes = matchedNodes.models.map(node => ({ diff --git a/ui/tests/acceptance/search-test.js b/ui/tests/acceptance/search-test.js index 22cbe6a448ea..635aa0ee9b5b 100644 --- a/ui/tests/acceptance/search-test.js +++ b/ui/tests/acceptance/search-test.js @@ -16,8 +16,19 @@ module('Acceptance | search', function(hooks) { server.create('node', { name: 'xyz' }); const otherNode = server.create('node', { name: 'ghi' }); - server.create('job', { id: 'vwxyz', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 }); - server.create('job', { id: 'xyz', name: 'xyz job', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 }); + server.create('job', { + id: 'vwxyz', + namespaceId: 'default', + groupsCount: 1, + groupTaskCount: 1, + }); + server.create('job', { + id: 'xyz', + name: 'xyz job', + namespaceId: 'default', + groupsCount: 1, + groupTaskCount: 1, + }); server.create('job', { id: 'abc', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 }); const firstAllocation = server.schema.allocations.all().models[0]; @@ -35,8 +46,8 @@ module('Acceptance | search', function(hooks) { search.groups[0].as(jobs => { assert.equal(jobs.name, 'Jobs (2)'); assert.equal(jobs.options.length, 2); - assert.equal(jobs.options[0].text, 'vwxyz'); - assert.equal(jobs.options[1].text, 'xyz job'); + assert.equal(jobs.options[0].text, 'default > vwxyz'); + assert.equal(jobs.options[1].text, 'default > xyz job'); }); search.groups[1].as(clients => { @@ -70,12 +81,18 @@ module('Acceptance | search', function(hooks) { assert.equal(currentURL(), `/clients/${otherNode.id}`); await selectSearch(Layout.navbar.search.scope, firstAllocation.name); - assert.equal(Layout.navbar.search.groups[2].options[0].text, firstAllocation.name); + assert.equal( + Layout.navbar.search.groups[2].options[0].text, + `${firstAllocation.namespace} > ${firstAllocation.name}` + ); await Layout.navbar.search.groups[2].options[0].click(); assert.equal(currentURL(), `/allocations/${firstAllocation.id}`); await selectSearch(Layout.navbar.search.scope, firstTaskGroup.name); - assert.equal(Layout.navbar.search.groups[3].options[0].text, firstTaskGroup.name); + assert.equal( + Layout.navbar.search.groups[3].options[0].text, + `default > vwxyz > ${firstTaskGroup.name}` + ); await Layout.navbar.search.groups[3].options[0].click(); assert.equal(currentURL(), `/jobs/vwxyz/${firstTaskGroup.name}`); @@ -83,11 +100,25 @@ module('Acceptance | search', function(hooks) { await Layout.navbar.search.groups[4].options[0].click(); assert.equal(currentURL(), '/csi/plugins/xyz-plugin'); - const featureDetectionQueries = server.pretender.handledRequests - .filterBy('url', '/v1/search/fuzzy') - .filter(request => request.requestBody.includes('feature-detection-query')); + const fuzzySearchQueries = server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy'); + + const featureDetectionQueries = fuzzySearchQueries.filter(request => + request.requestBody.includes('feature-detection-query') + ); - assert.equal(featureDetectionQueries.length, 1, 'expect the feature detection query to only run once'); + assert.ok( + featureDetectionQueries.length, + 1, + 'expect the feature detection query to only run once' + ); + + const realFuzzySearchQuery = fuzzySearchQueries[1]; + + assert.deepEqual(JSON.parse(realFuzzySearchQuery.requestBody), { + Context: 'all', + Namespace: '*', + Text: 'xy', + }); }); test('search does not perform a request when only one character has been entered', async function(assert) { @@ -96,7 +127,11 @@ module('Acceptance | search', function(hooks) { await selectSearch(Layout.navbar.search.scope, 'q'); assert.ok(Layout.navbar.search.noOptionsShown); - assert.equal(server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy').length, 1, 'expect the feature detection query'); + assert.equal( + server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy').length, + 1, + 'expect the feature detection query' + ); }); test('when fuzzy search is disabled on the server, the search control is hidden', async function(assert) {