Skip to content

Commit c25c1e6

Browse files
authored
chore(search-indexes): add segmented control for search indexes COMPASS-7162 (#4816)
* chore: add segmented control for search indexes * chore: add tests to the new functionality * chore: remove the .only * chore: fix linter issues * chore: optimise imports * chore: fix naming
1 parent b7fec80 commit c25c1e6

File tree

3 files changed

+135
-11
lines changed

3 files changed

+135
-11
lines changed

packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.spec.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const renderIndexesToolbar = (
2525
onRefreshIndexes={() => {}}
2626
isAtlasSearchSupported={false}
2727
isRefreshing={false}
28+
onChangeIndexView={() => {}}
2829
{...props}
2930
/>
3031
);
@@ -256,4 +257,61 @@ describe('IndexesToolbar Component', function () {
256257
});
257258
});
258259
});
260+
261+
describe('segment control', function () {
262+
describe('available when atlas search management is active', function () {
263+
let sandbox: sinon.SinonSandbox;
264+
let onChangeViewCallback: sinon.SinonSpy;
265+
266+
afterEach(function () {
267+
return sandbox.restore();
268+
});
269+
270+
beforeEach(function () {
271+
sandbox = sinon.createSandbox();
272+
sandbox.stub(preferencesAccess, 'getPreferences').returns({
273+
enableAtlasSearchIndexManagement: true,
274+
showInsights: true,
275+
} as any);
276+
277+
onChangeViewCallback = sinon.spy();
278+
});
279+
280+
describe('when atlas search is supported in the cluster', function () {
281+
beforeEach(function () {
282+
renderIndexesToolbar({
283+
isAtlasSearchSupported: true,
284+
onChangeIndexView: onChangeViewCallback,
285+
});
286+
});
287+
288+
it('should change to search indexes when the segment control is clicked', function () {
289+
const segmentControl = screen.getByText('Search Indexes');
290+
userEvent.click(segmentControl);
291+
292+
expect(onChangeViewCallback).to.have.been.calledOnce;
293+
expect(onChangeViewCallback.firstCall.args[0]).to.equal(
294+
'search-indexes'
295+
);
296+
});
297+
});
298+
299+
describe('when atlas search is not supported in the cluster', function () {
300+
beforeEach(function () {
301+
renderIndexesToolbar({
302+
isAtlasSearchSupported: false,
303+
onChangeIndexView: onChangeViewCallback,
304+
});
305+
});
306+
307+
it('should not change to search indexes', function () {
308+
const segmentControl = screen.getByText('Search Indexes');
309+
userEvent.click(segmentControl);
310+
311+
expect(segmentControl.closest('button')).to.have.attr('disabled');
312+
expect(onChangeViewCallback).to.not.have.been.calledOnce;
313+
});
314+
});
315+
});
316+
});
259317
});

packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
SignalPopover,
1313
PerformanceSignals,
1414
DropdownMenuButton,
15+
SegmentedControl,
16+
SegmentedControlOption,
1517
} from '@mongodb-js/compass-components';
1618
import type AppRegistry from 'hadron-app-registry';
1719
import { usePreference } from 'compass-preferences-model';
@@ -28,6 +30,10 @@ const toolbarButtonsContainer = css({
2830
alignItems: 'center',
2931
});
3032

33+
const alignSelfEndStyles = css({
34+
marginLeft: 'auto',
35+
});
36+
3137
const errorStyles = css({ marginTop: spacing[2] });
3238
const spinnerStyles = css({ marginRight: spacing[2] });
3339

@@ -36,6 +42,8 @@ const createIndexButtonContainerStyles = css({
3642
width: 'fit-content',
3743
});
3844

45+
export type IndexView = 'regular-indexes' | 'search-indexes';
46+
3947
type IndexesToolbarProps = {
4048
errorMessage: string | null;
4149
isReadonlyView: boolean;
@@ -46,6 +54,7 @@ type IndexesToolbarProps = {
4654
writeStateDescription?: string;
4755
isAtlasSearchSupported: boolean;
4856
onRefreshIndexes: () => void;
57+
onChangeIndexView: (newView: IndexView) => void;
4958
readOnly?: boolean;
5059
};
5160

@@ -59,6 +68,7 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
5968
hasTooManyIndexes,
6069
isAtlasSearchSupported,
6170
onRefreshIndexes,
71+
onChangeIndexView,
6272
readOnly, // preferences readOnly.
6373
}) => {
6474
const isSearchManagementActive = usePreference(
@@ -73,6 +83,14 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
7383
const onClickCreateAtlasSearchIndex = useCallback(() => {
7484
localAppRegistry.emit('open-create-search-index-modal');
7585
}, [localAppRegistry]);
86+
const onChangeIndexesSegment = useCallback(
87+
(value: string) => {
88+
const newView = value as IndexView;
89+
onChangeIndexView(newView);
90+
},
91+
[onChangeIndexView]
92+
);
93+
7694
const showCreateIndexButton = !isReadonlyView && !readOnly && !errorMessage;
7795
const refreshButtonIcon = isRefreshing ? (
7896
<div className={spinnerStyles}>
@@ -132,6 +150,43 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
132150
signals={PerformanceSignals.get('too-many-indexes')}
133151
/>
134152
)}
153+
{isSearchManagementActive && (
154+
<SegmentedControl
155+
onChange={onChangeIndexesSegment}
156+
className={alignSelfEndStyles}
157+
label="Viewing"
158+
defaultValue="regular-indexes"
159+
>
160+
<SegmentedControlOption value="regular-indexes">
161+
Indexes
162+
</SegmentedControlOption>
163+
{!isAtlasSearchSupported && (
164+
<Tooltip
165+
align="top"
166+
justify="middle"
167+
enabled={true}
168+
delay={500}
169+
trigger={({ children, ...props }) => (
170+
<SegmentedControlOption
171+
{...props}
172+
value="search-indexes"
173+
disabled={true}
174+
>
175+
Search Indexes
176+
{children}
177+
</SegmentedControlOption>
178+
)}
179+
>
180+
Search indexes are unavailable in your current connection.
181+
</Tooltip>
182+
)}
183+
{isAtlasSearchSupported && (
184+
<SegmentedControlOption value="search-indexes">
185+
Search Indexes
186+
</SegmentedControlOption>
187+
)}
188+
</SegmentedControl>
189+
)}
135190
</div>
136191
</div>
137192
)}

packages/compass-indexes/src/components/indexes/indexes.tsx

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22
import { css, spacing } from '@mongodb-js/compass-components';
33
import { connect } from 'react-redux';
44
import type AppRegistry from 'hadron-app-registry';
@@ -17,6 +17,7 @@ import type {
1717
SortDirection,
1818
} from '../../modules/regular-indexes';
1919

20+
import type { IndexView } from '../indexes-toolbar/indexes-toolbar';
2021
import { IndexesToolbar } from '../indexes-toolbar/indexes-toolbar';
2122
import { IndexesTable } from '../indexes-table/indexes-table';
2223
import type { RootState } from '../../modules';
@@ -66,6 +67,9 @@ export const Indexes: React.FunctionComponent<IndexesProps> = ({
6667
onUnhideIndex,
6768
readOnly, // preferences readOnly.
6869
}) => {
70+
const [currentIndexesView, setCurrentIndexesView] =
71+
useState<IndexView>('regular-indexes');
72+
6973
const deleteIndex = (index: IndexDefinition) => {
7074
if (index.extra.status === 'failed') {
7175
return dropFailedIndex(String(index.extra.id));
@@ -87,17 +91,24 @@ export const Indexes: React.FunctionComponent<IndexesProps> = ({
8791
hasTooManyIndexes={indexes.length > IDEAL_NUMBER_OF_MAX_INDEXES}
8892
isAtlasSearchSupported={true}
8993
onRefreshIndexes={refreshIndexes}
94+
onChangeIndexView={setCurrentIndexesView}
9095
/>
91-
{!isReadonlyView && !error && (
92-
<IndexesTable
93-
indexes={indexes}
94-
serverVersion={serverVersion}
95-
canModifyIndex={isWritable && !readOnly}
96-
onSortTable={sortIndexes}
97-
onDeleteIndex={deleteIndex}
98-
onHideIndex={onHideIndex}
99-
onUnhideIndex={onUnhideIndex}
100-
/>
96+
{!isReadonlyView &&
97+
!error &&
98+
currentIndexesView === 'regular-indexes' && (
99+
<IndexesTable
100+
indexes={indexes}
101+
serverVersion={serverVersion}
102+
canModifyIndex={isWritable && !readOnly}
103+
onSortTable={sortIndexes}
104+
onDeleteIndex={deleteIndex}
105+
onHideIndex={onHideIndex}
106+
onUnhideIndex={onUnhideIndex}
107+
/>
108+
)}
109+
110+
{!isReadonlyView && !error && currentIndexesView === 'search-indexes' && (
111+
<p style={{ textAlign: 'center' }}>In Progress feature</p>
101112
)}
102113
</div>
103114
);

0 commit comments

Comments
 (0)