Skip to content

Commit

Permalink
Merge pull request #10666 from hashicorp/b-ui/search-namespaces
Browse files Browse the repository at this point in the history
ui: Fix fuzzy search namespace-handling
  • Loading branch information
ChaiWithJai authored and Mahmood Ali committed Aug 26, 2021
1 parent 42e14ac commit a57193d
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 43 deletions.
3 changes: 3 additions & 0 deletions .changelog/10666.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
ui: Add ability to search across all namespaces
```
84 changes: 54 additions & 30 deletions ui/app/components/global-search/control.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default class GlobalSearchControl extends Component {
body: JSON.stringify({
Text: string,
Context: 'all',
Namespace: '*',
}),
});

Expand All @@ -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',
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions ui/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 => ({
Expand All @@ -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 => ({
Expand Down
57 changes: 46 additions & 11 deletions ui/tests/acceptance/search-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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 => {
Expand Down Expand Up @@ -70,24 +81,44 @@ 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}`);

await selectSearch(Layout.navbar.search.scope, 'xy');
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) {
Expand All @@ -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) {
Expand Down

0 comments on commit a57193d

Please sign in to comment.