Skip to content

Commit 8eec63f

Browse files
authored
feat: Add UI without functionality for "Start with an index" flow CLOUDP-311781 (#6874)
* set up border and covered queries button * set up most of the styling for index flow * finished styling + added tooltip and code equivalent * updated styling to center more things * added tests * do not need to import font * reverted the control back to initial state * temporarily rmeove tests * adding back tests * address pr comments * fixed infosprinkle and calls to CreateIndexFields
1 parent 16960de commit 8eec63f

File tree

3 files changed

+280
-18
lines changed

3 files changed

+280
-18
lines changed

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

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
useConnectionSupports,
1919
} from '@mongodb-js/compass-connections/provider';
2020
import { usePreference } from 'compass-preferences-model/provider';
21+
import IndexFlowSection from './index-flow-section';
2122

2223
const createIndexModalFieldsStyles = css({
2324
margin: `${spacing[600]}px 0 ${spacing[800]}px 0`,
@@ -79,13 +80,22 @@ function CreateIndexForm({
7980
});
8081
}, [schemaFields]);
8182

83+
const showIndexesGuidanceIndexFlow =
84+
showIndexesGuidanceVariant && currentTab === 'IndexFlow';
85+
const showIndexesGuidanceQueryFlow =
86+
showIndexesGuidanceVariant && currentTab === 'QueryFlow';
87+
8288
return (
8389
<>
8490
<div
8591
className={createIndexModalFieldsStyles}
8692
data-testid="create-index-form"
8793
>
88-
{showIndexesGuidanceVariant ? (
94+
{!showIndexesGuidanceVariant ? (
95+
<Body weight="medium" className={indexFieldsHeaderStyles}>
96+
Index fields
97+
</Body>
98+
) : (
8999
<RadioBoxGroup
90100
aria-labelledby="index-flows"
91101
data-testid="create-index-form-flows"
@@ -103,27 +113,44 @@ function CreateIndexForm({
103113
Start with a Query
104114
</RadioBox>
105115
</RadioBoxGroup>
106-
) : (
107-
<Body weight="medium" className={indexFieldsHeaderStyles}>
108-
Index fields
109-
</Body>
110116
)}
111117

112-
{/* Only show the fields if user is in the Start with an index flow or if they're in the control */}
113-
{fields.length > 0 &&
114-
(!showIndexesGuidanceVariant || currentTab === 'IndexFlow') ? (
115-
<CreateIndexFields
116-
schemaFields={schemaFieldNames}
117-
fields={fields}
118-
serverVersion={serverVersion}
119-
isRemovable={!(fields.length > 1)}
120-
onSelectFieldNameClick={onSelectFieldNameClick}
121-
onSelectFieldTypeClick={onSelectFieldTypeClick}
122-
onAddFieldClick={onAddFieldClick}
123-
onRemoveFieldClick={onRemoveFieldClick}
124-
/>
118+
{fields.length > 0 ? (
119+
// Variant UI
120+
showIndexesGuidanceVariant && showIndexesGuidanceIndexFlow ? (
121+
<IndexFlowSection
122+
createIndexFieldsComponent={
123+
<CreateIndexFields
124+
schemaFields={schemaFieldNames}
125+
fields={fields}
126+
serverVersion={serverVersion}
127+
isRemovable={!(fields.length > 1)}
128+
onSelectFieldNameClick={onSelectFieldNameClick}
129+
onSelectFieldTypeClick={onSelectFieldTypeClick}
130+
onAddFieldClick={onAddFieldClick}
131+
onRemoveFieldClick={onRemoveFieldClick}
132+
/>
133+
}
134+
/>
135+
) : (
136+
// Control UI
137+
!showIndexesGuidanceQueryFlow && (
138+
<CreateIndexFields
139+
schemaFields={schemaFieldNames}
140+
fields={fields}
141+
serverVersion={serverVersion}
142+
isRemovable={!(fields.length > 1)}
143+
onSelectFieldNameClick={onSelectFieldNameClick}
144+
onSelectFieldTypeClick={onSelectFieldTypeClick}
145+
onAddFieldClick={onAddFieldClick}
146+
onRemoveFieldClick={onRemoveFieldClick}
147+
/>
148+
)
149+
)
125150
) : null}
126151
</div>
152+
153+
{/* TODO in CLOUDP-314036: update the accordion design */}
127154
<Accordion data-testid="create-index-modal-toggle-options" text="Options">
128155
<div
129156
data-testid="create-index-modal-options"
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from 'react';
2+
import { render, screen } from '@mongodb-js/testing-library-compass';
3+
import IndexFlowSection from './index-flow-section';
4+
import { expect } from 'chai';
5+
6+
describe('IndexFlowSection', () => {
7+
const renderComponent = (createIndexFieldsComponent?: JSX.Element) => {
8+
render(
9+
<IndexFlowSection
10+
createIndexFieldsComponent={createIndexFieldsComponent ?? null}
11+
/>
12+
);
13+
};
14+
it('renders the Input Index header', () => {
15+
renderComponent();
16+
expect(screen.getByText('Input Index')).to.be.visible;
17+
});
18+
19+
it('renders the Code Equivalent toggle', () => {
20+
renderComponent();
21+
expect(screen.getByLabelText('Toggle Code Equivalent')).to.be.visible;
22+
});
23+
24+
it('renders the Show me covered queries button', () => {
25+
renderComponent();
26+
expect(screen.getByText('Show me covered queries')).to.be.visible;
27+
});
28+
29+
it('renders the Covered Queries header', () => {
30+
renderComponent();
31+
expect(screen.getByText('Covered Queries')).to.be.visible;
32+
});
33+
34+
it('renders the provided createIndexFieldsComponent', () => {
35+
const mockComponent = (
36+
<div data-testid="mock-component">Mock Component</div>
37+
);
38+
renderComponent(mockComponent);
39+
expect(screen.getByTestId('mock-component')).to.be.visible;
40+
});
41+
42+
it('renders the covered queries examples', () => {
43+
renderComponent();
44+
expect(screen.getByTestId('index-flow-section-covered-queries-examples')).to
45+
.exist;
46+
});
47+
48+
it('renders the optimal query examples', () => {
49+
renderComponent();
50+
expect(screen.getByTestId('index-flow-section-optimal-query-examples')).to
51+
.exist;
52+
});
53+
54+
it('renders the Learn More link', () => {
55+
renderComponent();
56+
const link = screen.getByText('Learn More');
57+
expect(link).to.be.visible;
58+
});
59+
});
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import {
2+
Body,
3+
Button,
4+
css,
5+
cx,
6+
Label,
7+
Link,
8+
palette,
9+
spacing,
10+
Toggle,
11+
fontFamilies,
12+
InfoSprinkle,
13+
} from '@mongodb-js/compass-components';
14+
import React from 'react';
15+
16+
const flexContainerStyles = css({
17+
display: 'flex',
18+
alignItems: 'center',
19+
});
20+
21+
const indexFieldsHeaderContainerStyles = css({
22+
justifyContent: 'space-between',
23+
marginBottom: spacing[200],
24+
});
25+
26+
const indexFieldsCalloutStyles = css({
27+
border: `1px solid ${palette.gray.light2}`,
28+
borderRadius: '12px',
29+
padding: spacing[600],
30+
marginBottom: spacing[600],
31+
});
32+
33+
const codeEquivalentToggleLabelStyles = css({
34+
marginRight: spacing[100],
35+
fontWeight: 'normal',
36+
});
37+
38+
const coveredQueriesHeaderContainerStyles = css({
39+
marginBottom: spacing[200],
40+
});
41+
42+
const coveredQueriesCalloutStyles = css({
43+
border: `1px solid ${palette.gray.light2}`,
44+
background: palette.gray.light3,
45+
borderRadius: '12px',
46+
padding: spacing[600],
47+
marginBottom: spacing[600],
48+
});
49+
50+
const buttonContainerStyles = css({
51+
display: 'flex',
52+
justifyContent: 'right',
53+
});
54+
55+
const coveredQueriesButtonStyles = css({
56+
float: 'right',
57+
marginTop: spacing[400],
58+
});
59+
60+
const underlineStyles = css({
61+
textDecoration: 'underline',
62+
});
63+
64+
const codeStyles = css({
65+
fontFamily: fontFamilies.code,
66+
});
67+
68+
const coveredQueriesHeaderStyles = css({
69+
marginRight: spacing[200],
70+
});
71+
72+
export type IndexFlowSectionProps = {
73+
createIndexFieldsComponent: JSX.Element | null;
74+
};
75+
76+
const IndexFlowSection = ({
77+
createIndexFieldsComponent,
78+
}: IndexFlowSectionProps) => {
79+
return (
80+
<div>
81+
<div
82+
className={cx(indexFieldsHeaderContainerStyles, flexContainerStyles)}
83+
>
84+
<Body baseFontSize={16} weight="medium">
85+
Input Index
86+
</Body>
87+
<div className={flexContainerStyles}>
88+
<Label
89+
className={codeEquivalentToggleLabelStyles}
90+
htmlFor="code-equivalent-toggle"
91+
>
92+
Code Equivalent
93+
</Label>
94+
95+
<Toggle
96+
size="xsmall"
97+
id="code-equivalent-toggle"
98+
aria-label="Toggle Code Equivalent"
99+
onChange={() => {
100+
() => {
101+
// TODO in CLOUDP-311784
102+
};
103+
}}
104+
// checked={false}
105+
/>
106+
</div>
107+
</div>
108+
<div className={indexFieldsCalloutStyles}>
109+
{createIndexFieldsComponent}
110+
111+
<div className={buttonContainerStyles}>
112+
<Button
113+
className={coveredQueriesButtonStyles}
114+
onClick={() => {
115+
// TODO in CLOUDP-311782 generate covered queries
116+
// TODO in CLOUDP-311783 generate optimal queries
117+
}}
118+
size="small"
119+
>
120+
Show me covered queries
121+
</Button>
122+
</div>
123+
</div>
124+
125+
<div
126+
className={cx(coveredQueriesHeaderContainerStyles, flexContainerStyles)}
127+
>
128+
<Body
129+
baseFontSize={16}
130+
weight="medium"
131+
className={coveredQueriesHeaderStyles}
132+
>
133+
Covered Queries
134+
</Body>
135+
136+
<InfoSprinkle align="top" justify="middle">
137+
{' '}
138+
A covered query is a query that can be satisfied entirely using an
139+
index and does not have to examine any documents. If a query is
140+
covered, it is highly performant.
141+
</InfoSprinkle>
142+
</div>
143+
144+
<div className={coveredQueriesCalloutStyles}>
145+
{/* Covered Queries, clean up with actual covered queries examples in CLOUDP-311782 */}
146+
<Body
147+
className={codeStyles}
148+
data-testid="index-flow-section-covered-queries-examples"
149+
>
150+
{`{ awards.wins:3 }`} <br />
151+
{`{ awards.wins:3, imdb.rating:5 }`} <br />
152+
{`{ awards.wins:3, imdb.rating:5, awards.nominations:8 }`} <br />
153+
</Body>
154+
<p>
155+
<span className={underlineStyles}>
156+
Follow the Equality, Sort, Range (ESR) Rule and this index is
157+
optimal for queries that have this pattern:
158+
</span>
159+
{/* Optimal queries, clean up with actual optimal queries in CLOUDP-311783 */}
160+
<Body
161+
className={codeStyles}
162+
data-testid="index-flow-section-optimal-query-examples"
163+
>
164+
{`{ awards.wins : 5, imdb.rating: {$gt : 5} }.sort({ awards.nominations : 1 }`}
165+
</Body>
166+
</p>
167+
168+
<Link href="https://www.mongodb.com/docs/manual/core/query-optimization/">
169+
Learn More
170+
</Link>
171+
</div>
172+
</div>
173+
);
174+
};
175+
176+
export default IndexFlowSection;

0 commit comments

Comments
 (0)