Skip to content

Commit def8c21

Browse files
authored
feat(search-indexes): add a drop down to choose a search index template COMPASS-7173 (#4892)
* chore: add template to both create and update modals * chore: replace template on creating and updating * chore: bump to the latest mongodb-constants * chore: bump to latest mongodb-constants * chore: fix dependencies * chore: fix linter issues * chore: fix peer deps * chore: fix package-lock * chore: fix peer deps * chore: fix potential weird behaviour on focus and applySnippet * chore: fix test, now codemirror content is async due to rafraf * chore: fix style issues in dropdown * chore: remove overflow hidden on body to avoid issues on small screens * chore: merge with main, fix dependencies * chore: minor fixes * chore: forgot to remove .only for testing * chore: bump constants package
1 parent 8596ab8 commit def8c21

File tree

12 files changed

+321
-129
lines changed

12 files changed

+321
-129
lines changed

package-lock.json

Lines changed: 74 additions & 91 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"@babel/core": "7.16.0",
6262
"@babel/parser": "7.16.0",
6363
"@mongodb-js/monorepo-tools": "^1.1.1",
64-
"@mongodb-js/sbom-tools": "^0.5.3",
64+
"@mongodb-js/sbom-tools": "^0.5.2",
6565
"@testing-library/dom": "^8.11.1",
6666
"babel-loader": "^7.1.5",
6767
"husky": "^8.0.3",

packages/compass-aggregations/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"@mongodb-js/compass-user-data": "^0.1.2",
4747
"@mongodb-js/compass-utils": "^0.4.0",
4848
"@mongodb-js/explain-plan-helper": "^1.1.2",
49-
"@mongodb-js/mongodb-constants": "^0.8.3",
49+
"@mongodb-js/mongodb-constants": "^0.8.4",
5050
"@mongodb-js/mongodb-redux-common": "^2.0.11",
5151
"bson": "^6.0.0",
5252
"compass-preferences-model": "^2.14.0",
@@ -106,7 +106,7 @@
106106
"@mongodb-js/compass-user-data": "^0.1.2",
107107
"@mongodb-js/compass-utils": "^0.4.0",
108108
"@mongodb-js/explain-plan-helper": "^1.1.2",
109-
"@mongodb-js/mongodb-constants": "^0.8.3",
109+
"@mongodb-js/mongodb-constants": "^0.8.4",
110110
"@mongodb-js/mongodb-redux-common": "^2.0.11",
111111
"bson": "^6.0.0",
112112
"compass-preferences-model": "^2.14.0",

packages/compass-e2e-tests/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"ps-list": "^8.1.0",
6464
"puppeteer": "^15.4.0",
6565
"resolve-mongodb-srv": "^1.1.2",
66-
"semver": "^7.5.0",
66+
"semver": "^7.5.4",
6767
"ts-node": "^10.9.1",
6868
"webdriverio": "^7.16.13",
6969
"xvfb-maybe": "^0.2.1"

packages/compass-editor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"@codemirror/view": "^6.7.1",
7777
"@lezer/highlight": "^1.1.3",
7878
"@mongodb-js/compass-components": "^1.14.0",
79-
"@mongodb-js/mongodb-constants": "^0.8.3",
79+
"@mongodb-js/mongodb-constants": "^0.8.4",
8080
"polished": "^4.2.2",
8181
"prettier": "^2.7.1"
8282
}

packages/compass-indexes/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"@mongodb-js/compass-editor": "^0.13.0",
6161
"@mongodb-js/compass-logging": "^1.2.0",
6262
"@mongodb-js/mongodb-redux-common": "^2.0.11",
63+
"@mongodb-js/mongodb-constants": "^0.8.4",
6364
"bson": "^6.0.0",
6465
"compass-preferences-model": "^2.14.0",
6566
"react": "^17.0.2"
@@ -74,6 +75,7 @@
7475
"@testing-library/user-event": "^13.5.0",
7576
"chai": "^4.2.0",
7677
"depcheck": "^1.4.1",
78+
"ejson-shell-parser": "^1.2.4",
7779
"electron": "^26.2.2",
7880
"enzyme": "^3.11.0",
7981
"eslint": "^7.25.0",
@@ -93,14 +95,14 @@
9395
"redux-thunk": "^2.4.1",
9496
"semver": "^5.4.1",
9597
"sinon": "^9.2.3",
96-
"xvfb-maybe": "^0.2.1",
97-
"ejson-shell-parser": "^1.2.4"
98+
"xvfb-maybe": "^0.2.1"
9899
},
99100
"dependencies": {
100101
"@mongodb-js/compass-components": "^1.14.0",
101102
"@mongodb-js/compass-editor": "^0.13.0",
102103
"@mongodb-js/compass-logging": "^1.2.0",
103104
"@mongodb-js/mongodb-redux-common": "^2.0.11",
105+
"@mongodb-js/mongodb-constants": "^0.8.4",
104106
"bson": "^6.0.0",
105107
"compass-preferences-model": "^2.14.0"
106108
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { ATLAS_SEARCH_TEMPLATES } from '@mongodb-js/mongodb-constants';
2+
import { expect } from 'chai';
3+
import { SearchIndexTemplateDropdown } from './';
4+
import sinon from 'sinon';
5+
import type { SinonSpy } from 'sinon';
6+
7+
import { render, screen, cleanup } from '@testing-library/react';
8+
import userEvent from '@testing-library/user-event';
9+
10+
import React from 'react';
11+
12+
function templateNamed(name: string) {
13+
return ATLAS_SEARCH_TEMPLATES.find((t) => t.name === name);
14+
}
15+
16+
describe('Search Index Template Dropdown', function () {
17+
let onTemplateSpy: SinonSpy;
18+
19+
beforeEach(function () {
20+
onTemplateSpy = sinon.spy();
21+
22+
render(
23+
<SearchIndexTemplateDropdown
24+
tooltip="Tooltip"
25+
onTemplate={onTemplateSpy}
26+
/>
27+
);
28+
});
29+
30+
afterEach(cleanup);
31+
32+
it('notifies upwards with onTemplate when a new template is choosen', async function () {
33+
const dropDown = screen
34+
.getByText('Dynamic field mappings')
35+
.closest('button')!;
36+
37+
userEvent.click(dropDown);
38+
39+
const staticFieldMappingOption = await screen.findByText(
40+
'Static field mappings'
41+
);
42+
userEvent.click(staticFieldMappingOption);
43+
44+
expect(onTemplateSpy).to.have.been.calledWith(
45+
templateNamed('Static field mappings')
46+
);
47+
});
48+
});
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { ATLAS_SEARCH_TEMPLATES } from '@mongodb-js/mongodb-constants';
2+
import type { SearchTemplate } from '@mongodb-js/mongodb-constants';
3+
import React, { useState, useCallback } from 'react';
4+
import {
5+
Select,
6+
Option,
7+
Icon,
8+
css,
9+
Tooltip,
10+
} from '@mongodb-js/compass-components';
11+
12+
const dropdownLabelStyles = css({
13+
display: 'flex',
14+
pointerEvents: 'auto', // leafy green specifies none in the label, which is wrong
15+
});
16+
17+
const fillParentStyles = css({
18+
flexGrow: 1,
19+
});
20+
21+
type SearchIndexTemplateDropdownLabelProps = {
22+
label: string;
23+
tooltip: string;
24+
};
25+
26+
const SearchIndexTemplateDropdownLabel: React.FunctionComponent<
27+
SearchIndexTemplateDropdownLabelProps
28+
> = ({ label, tooltip }) => (
29+
<div className={dropdownLabelStyles}>
30+
<span className={fillParentStyles}>{label}</span>
31+
<Tooltip
32+
align="right"
33+
triggerEvent="hover"
34+
trigger={({ children, ...props }) => (
35+
<div {...props}>
36+
<Icon
37+
data-testid="search-template-info-icon"
38+
glyph="InfoWithCircle"
39+
/>
40+
{children}
41+
</div>
42+
)}
43+
>
44+
{tooltip}
45+
</Tooltip>
46+
</div>
47+
);
48+
49+
type SearchIndexTemplateDropdownProps = {
50+
tooltip: string;
51+
onTemplate: (template: SearchTemplate) => void;
52+
};
53+
54+
export const SearchIndexTemplateDropdown: React.FunctionComponent<
55+
SearchIndexTemplateDropdownProps
56+
> = ({ tooltip, onTemplate }) => {
57+
const [templateValue, setTemplateValue] = useState('0');
58+
59+
const onChooseTemplate = useCallback(
60+
(value: string) => {
61+
setTemplateValue(value);
62+
onTemplate(ATLAS_SEARCH_TEMPLATES[+value]);
63+
},
64+
[onTemplate]
65+
);
66+
67+
return (
68+
<Select
69+
value={templateValue}
70+
allowDeselect={false}
71+
onChange={onChooseTemplate}
72+
/* @ts-expect-error The label can be any React component, however, the type definition forces a string. */
73+
label={
74+
<SearchIndexTemplateDropdownLabel label="Template" tooltip={tooltip} />
75+
}
76+
>
77+
{ATLAS_SEARCH_TEMPLATES.map((template, idx) => (
78+
<Option key={idx} value={`${idx}`}>
79+
{template.name}
80+
</Option>
81+
))}
82+
</Select>
83+
);
84+
};

packages/compass-indexes/src/components/search-indexes-modals/base-search-index-modal.spec.tsx

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
1+
import { ATLAS_SEARCH_TEMPLATES } from '@mongodb-js/mongodb-constants';
12
import { expect } from 'chai';
23
import { BaseSearchIndexModal } from './base-search-index-modal';
34
import sinon from 'sinon';
45
import type { SinonSpy } from 'sinon';
56

6-
import { render, screen, cleanup } from '@testing-library/react';
7+
import { render, screen, cleanup, waitFor } from '@testing-library/react';
78
import userEvent from '@testing-library/user-event';
89

910
import React from 'react';
1011
import { getCodemirrorEditorValue } from '@mongodb-js/compass-editor';
1112

13+
function normalizedTemplateNamed(name: string) {
14+
const snippet =
15+
ATLAS_SEARCH_TEMPLATES.find((t) => t.name === name)?.snippet || '';
16+
// code mirror 'changes' the template placeholders, so let's do the same
17+
// this regexp removes `tab` markers to their default value, for example:
18+
// ${1:default} => default
19+
//
20+
return snippet.replace(/\${\d+:([^}]+)}/gm, '$1');
21+
}
22+
1223
describe('Create Search Index Modal', function () {
1324
let onSubmitSpy: SinonSpy;
1425
let onCloseSpy: SinonSpy;
@@ -88,4 +99,27 @@ describe('Create Search Index Modal', function () {
8899
expect(onSubmitSpy).to.have.been.calledOnceWithExactly('default', {});
89100
});
90101
});
102+
103+
describe('templates', function () {
104+
it('replaces the contents of the index editor when a template is selected', async function () {
105+
const dropDown = screen
106+
.getByText('Dynamic field mappings')
107+
.closest('button')!;
108+
109+
userEvent.click(dropDown);
110+
111+
const staticFieldMappingOption = await screen.findByText(
112+
'Static field mappings'
113+
);
114+
userEvent.click(staticFieldMappingOption);
115+
116+
await waitFor(() => {
117+
const indexDef = getCodemirrorEditorValue('definition-of-search-index');
118+
119+
expect(indexDef).to.equal(
120+
normalizedTemplateNamed('Static field mappings')
121+
);
122+
});
123+
});
124+
});
91125
});

0 commit comments

Comments
 (0)