Skip to content

Commit 2fad963

Browse files
rubydongAnemy
andauthored
feat: Add UI for Start with a Query Flow CLOUDP-311785 (#6881)
* create query flow component * added a code copying section * added some more stylin for the input query * added programming language syntax link and more styling * add testing * using a variable that will be in another pr * updated index flow's copy and updated text input to codemirror editor * added autocomplete + fixed up tests * wrapped completer in a usememo * updated button name * fixed up spacing styles * styles: add focus ring, use multi-line editor * updated so button does not block text --------- Co-authored-by: Rhys Howell <[email protected]>
1 parent 1086d07 commit 2fad963

File tree

5 files changed

+217
-5
lines changed

5 files changed

+217
-5
lines changed

packages/compass-indexes/src/components/create-index-form/create-index-form.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from '@mongodb-js/compass-connections/provider';
2020
import { usePreference } from 'compass-preferences-model/provider';
2121
import IndexFlowSection from './index-flow-section';
22+
import QueryFlowSection from './query-flow-section';
2223

2324
const createIndexModalFieldsStyles = css({
2425
margin: `${spacing[600]}px 0 ${spacing[800]}px 0`,
@@ -150,6 +151,13 @@ function CreateIndexForm({
150151
) : null}
151152
</div>
152153

154+
{showIndexesGuidanceQueryFlow && (
155+
<QueryFlowSection
156+
schemaFields={schemaFields}
157+
serverVersion={serverVersion}
158+
/>
159+
)}
160+
153161
{/* TODO in CLOUDP-314036: update the accordion design */}
154162
<Accordion data-testid="create-index-modal-toggle-options" text="Options">
155163
<div

packages/compass-indexes/src/components/create-index-form/index-flow-section.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ describe('IndexFlowSection', () => {
2121
expect(screen.getByLabelText('Toggle Code Equivalent')).to.be.visible;
2222
});
2323

24-
it('renders the Show me covered queries button', () => {
24+
it('renders the Show covered queries button', () => {
2525
renderComponent();
26-
expect(screen.getByText('Show me covered queries')).to.be.visible;
26+
expect(screen.getByText('Show covered queries')).to.be.visible;
2727
});
2828

2929
it('renders the Covered Queries header', () => {

packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ const IndexFlowSection = ({
117117
}}
118118
size="small"
119119
>
120-
Show me covered queries
120+
Show covered queries
121121
</Button>
122122
</div>
123123
</div>
@@ -153,8 +153,8 @@ const IndexFlowSection = ({
153153
</Body>
154154
<p>
155155
<span className={underlineStyles}>
156-
Follow the Equality, Sort, Range (ESR) Rule and this index is
157-
optimal for queries that have this pattern:
156+
Follow the Equality, Sort, Range (ESR) Rule. This index is optimal
157+
for queries that have this pattern:
158158
</span>
159159
{/* Optimal queries, clean up with actual optimal queries in CLOUDP-311783 */}
160160
<Body
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
import { render, screen } from '@mongodb-js/testing-library-compass';
3+
import QueryFlowSection from './query-flow-section';
4+
import { expect } from 'chai';
5+
6+
describe('QueryFlowSection', () => {
7+
const renderComponent = () => {
8+
render(<QueryFlowSection schemaFields={[]} serverVersion="5.0.0" />);
9+
};
10+
it('renders the input query section with a code editor', () => {
11+
renderComponent();
12+
const codeEditor = screen.getByTestId('query-flow-section-code-editor');
13+
expect(codeEditor).to.be.visible;
14+
});
15+
16+
it('renders the "Show suggested index" button', () => {
17+
renderComponent();
18+
const buttonElement = screen.getByText('Show suggested index');
19+
expect(buttonElement).to.be.visible;
20+
});
21+
22+
it('renders the suggested index section with formatted index code', () => {
23+
renderComponent();
24+
const codeElement = screen.getByTestId(
25+
'query-flow-section-suggested-index'
26+
);
27+
expect(codeElement).to.be.visible;
28+
});
29+
30+
it('renders the link to the MongoDB documentation', () => {
31+
renderComponent();
32+
const linkElement = screen.getByText('here');
33+
expect(linkElement).to.be.visible;
34+
});
35+
});
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import {
2+
Button,
3+
palette,
4+
Body,
5+
Code,
6+
Link,
7+
cx,
8+
useFocusRing,
9+
} from '@mongodb-js/compass-components';
10+
import React, { useMemo } from 'react';
11+
import { css, spacing } from '@mongodb-js/compass-components';
12+
import {
13+
CodemirrorMultilineEditor,
14+
createQueryAutocompleter,
15+
} from '@mongodb-js/compass-editor';
16+
17+
const inputQueryContainerStyles = css({
18+
marginBottom: spacing[600],
19+
display: 'flex',
20+
flexDirection: 'column',
21+
});
22+
23+
const headerStyles = css({
24+
marginBottom: spacing[200],
25+
});
26+
27+
const suggestedIndexContainerStyles = css({
28+
flexDirection: 'column',
29+
display: 'flex',
30+
});
31+
32+
const editorActionContainerStyles = css({
33+
position: 'relative',
34+
});
35+
36+
const suggestedIndexButtonStyles = css({
37+
position: 'absolute',
38+
right: spacing[600],
39+
bottom: spacing[600],
40+
marginBottom: spacing[400],
41+
});
42+
43+
const editorContainerRadius = spacing[300];
44+
45+
const codeEditorContainerStyles = css({
46+
border: `1px solid ${palette.gray.base}`,
47+
borderRadius: editorContainerRadius,
48+
marginBottom: spacing[600],
49+
});
50+
51+
const codeEditorStyles = css({
52+
borderRadius: editorContainerRadius,
53+
'& .cm-editor': {
54+
background: `${palette.white} !important`,
55+
borderRadius: editorContainerRadius,
56+
},
57+
'& .cm-content': {
58+
padding: spacing[600],
59+
paddingBottom: spacing[1400],
60+
},
61+
});
62+
63+
const programmingLanguageLinkStyles = css({
64+
marginLeft: 'auto',
65+
marginTop: spacing[100],
66+
});
67+
68+
const QueryFlowSection = ({
69+
schemaFields,
70+
serverVersion,
71+
}: {
72+
schemaFields: { name: string; description?: string }[];
73+
serverVersion: string;
74+
}) => {
75+
// TODO in CLOUDP-311786, replace hardcoded values with actual data
76+
const db_name = 'sample_mflix';
77+
const collection_name = 'comments';
78+
79+
const formatSuggestedIndex = () => {
80+
return `
81+
db.getSiblingDB("${db_name}").getCollection("${collection_name}").createIndex(
82+
"awards.win": "1",
83+
"imdb.rating": "1",
84+
});
85+
`;
86+
};
87+
88+
const [inputQuery, setInputQuery] = React.useState('');
89+
const completer = useMemo(
90+
() =>
91+
createQueryAutocompleter({
92+
fields: schemaFields,
93+
serverVersion,
94+
}),
95+
[schemaFields, serverVersion]
96+
);
97+
98+
const focusRingProps = useFocusRing({
99+
outer: true,
100+
focusWithin: true,
101+
hover: true,
102+
radius: editorContainerRadius,
103+
});
104+
105+
return (
106+
<>
107+
<Body baseFontSize={16} weight="medium" className={headerStyles}>
108+
Input Query
109+
</Body>
110+
<div className={inputQueryContainerStyles}>
111+
<div
112+
className={cx(focusRingProps.className, codeEditorContainerStyles)}
113+
>
114+
<CodemirrorMultilineEditor
115+
data-testid="query-flow-section-code-editor"
116+
language="javascript-expression"
117+
showLineNumbers={false}
118+
minLines={5}
119+
showFoldGutter={false}
120+
showAnnotationsGutter={false}
121+
copyable={false}
122+
formattable={false}
123+
text={inputQuery}
124+
onChangeText={(text) => setInputQuery(text)}
125+
placeholder="Type a query: { field: 'value' }"
126+
completer={completer}
127+
className={codeEditorStyles}
128+
/>
129+
</div>
130+
131+
<div className={editorActionContainerStyles}>
132+
<Button
133+
onClick={() => {
134+
// TODO in CLOUDP-311786
135+
}}
136+
className={suggestedIndexButtonStyles}
137+
size="small"
138+
>
139+
Show suggested index
140+
</Button>
141+
</div>
142+
</div>
143+
<Body baseFontSize={16} weight="medium" className={headerStyles}>
144+
Suggested Index
145+
</Body>{' '}
146+
<div className={suggestedIndexContainerStyles}>
147+
<Code
148+
data-testid="query-flow-section-suggested-index"
149+
language="javascript"
150+
>
151+
{formatSuggestedIndex()}
152+
</Code>
153+
<span className={programmingLanguageLinkStyles}>
154+
View programming language driver syntax{' '}
155+
<Link
156+
href="https://www.mongodb.com/docs/manual/core/indexes/create-index/"
157+
target="_blank"
158+
rel="noreferrer noopener"
159+
>
160+
here
161+
</Link>
162+
.
163+
</span>
164+
</div>
165+
</>
166+
);
167+
};
168+
169+
export default QueryFlowSection;

0 commit comments

Comments
 (0)