Skip to content

Commit

Permalink
chore(search-indexes): add segmented control for search indexes COMPA…
Browse files Browse the repository at this point in the history
…SS-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
  • Loading branch information
kmruiz authored Sep 7, 2023
1 parent b7fec80 commit c25c1e6
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const renderIndexesToolbar = (
onRefreshIndexes={() => {}}
isAtlasSearchSupported={false}
isRefreshing={false}
onChangeIndexView={() => {}}
{...props}
/>
);
Expand Down Expand Up @@ -256,4 +257,61 @@ describe('IndexesToolbar Component', function () {
});
});
});

describe('segment control', function () {
describe('available when atlas search management is active', function () {
let sandbox: sinon.SinonSandbox;
let onChangeViewCallback: sinon.SinonSpy;

afterEach(function () {
return sandbox.restore();
});

beforeEach(function () {
sandbox = sinon.createSandbox();
sandbox.stub(preferencesAccess, 'getPreferences').returns({
enableAtlasSearchIndexManagement: true,
showInsights: true,
} as any);

onChangeViewCallback = sinon.spy();
});

describe('when atlas search is supported in the cluster', function () {
beforeEach(function () {
renderIndexesToolbar({
isAtlasSearchSupported: true,
onChangeIndexView: onChangeViewCallback,
});
});

it('should change to search indexes when the segment control is clicked', function () {
const segmentControl = screen.getByText('Search Indexes');
userEvent.click(segmentControl);

expect(onChangeViewCallback).to.have.been.calledOnce;
expect(onChangeViewCallback.firstCall.args[0]).to.equal(
'search-indexes'
);
});
});

describe('when atlas search is not supported in the cluster', function () {
beforeEach(function () {
renderIndexesToolbar({
isAtlasSearchSupported: false,
onChangeIndexView: onChangeViewCallback,
});
});

it('should not change to search indexes', function () {
const segmentControl = screen.getByText('Search Indexes');
userEvent.click(segmentControl);

expect(segmentControl.closest('button')).to.have.attr('disabled');
expect(onChangeViewCallback).to.not.have.been.calledOnce;
});
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
SignalPopover,
PerformanceSignals,
DropdownMenuButton,
SegmentedControl,
SegmentedControlOption,
} from '@mongodb-js/compass-components';
import type AppRegistry from 'hadron-app-registry';
import { usePreference } from 'compass-preferences-model';
Expand All @@ -28,6 +30,10 @@ const toolbarButtonsContainer = css({
alignItems: 'center',
});

const alignSelfEndStyles = css({
marginLeft: 'auto',
});

const errorStyles = css({ marginTop: spacing[2] });
const spinnerStyles = css({ marginRight: spacing[2] });

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

export type IndexView = 'regular-indexes' | 'search-indexes';

type IndexesToolbarProps = {
errorMessage: string | null;
isReadonlyView: boolean;
Expand All @@ -46,6 +54,7 @@ type IndexesToolbarProps = {
writeStateDescription?: string;
isAtlasSearchSupported: boolean;
onRefreshIndexes: () => void;
onChangeIndexView: (newView: IndexView) => void;
readOnly?: boolean;
};

Expand All @@ -59,6 +68,7 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
hasTooManyIndexes,
isAtlasSearchSupported,
onRefreshIndexes,
onChangeIndexView,
readOnly, // preferences readOnly.
}) => {
const isSearchManagementActive = usePreference(
Expand All @@ -73,6 +83,14 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
const onClickCreateAtlasSearchIndex = useCallback(() => {
localAppRegistry.emit('open-create-search-index-modal');
}, [localAppRegistry]);
const onChangeIndexesSegment = useCallback(
(value: string) => {
const newView = value as IndexView;
onChangeIndexView(newView);
},
[onChangeIndexView]
);

const showCreateIndexButton = !isReadonlyView && !readOnly && !errorMessage;
const refreshButtonIcon = isRefreshing ? (
<div className={spinnerStyles}>
Expand Down Expand Up @@ -132,6 +150,43 @@ export const IndexesToolbar: React.FunctionComponent<IndexesToolbarProps> = ({
signals={PerformanceSignals.get('too-many-indexes')}
/>
)}
{isSearchManagementActive && (
<SegmentedControl
onChange={onChangeIndexesSegment}
className={alignSelfEndStyles}
label="Viewing"
defaultValue="regular-indexes"
>
<SegmentedControlOption value="regular-indexes">
Indexes
</SegmentedControlOption>
{!isAtlasSearchSupported && (
<Tooltip
align="top"
justify="middle"
enabled={true}
delay={500}
trigger={({ children, ...props }) => (
<SegmentedControlOption
{...props}
value="search-indexes"
disabled={true}
>
Search Indexes
{children}
</SegmentedControlOption>
)}
>
Search indexes are unavailable in your current connection.
</Tooltip>
)}
{isAtlasSearchSupported && (
<SegmentedControlOption value="search-indexes">
Search Indexes
</SegmentedControlOption>
)}
</SegmentedControl>
)}
</div>
</div>
)}
Expand Down
33 changes: 22 additions & 11 deletions packages/compass-indexes/src/components/indexes/indexes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { css, spacing } from '@mongodb-js/compass-components';
import { connect } from 'react-redux';
import type AppRegistry from 'hadron-app-registry';
Expand All @@ -17,6 +17,7 @@ import type {
SortDirection,
} from '../../modules/regular-indexes';

import type { IndexView } from '../indexes-toolbar/indexes-toolbar';
import { IndexesToolbar } from '../indexes-toolbar/indexes-toolbar';
import { IndexesTable } from '../indexes-table/indexes-table';
import type { RootState } from '../../modules';
Expand Down Expand Up @@ -66,6 +67,9 @@ export const Indexes: React.FunctionComponent<IndexesProps> = ({
onUnhideIndex,
readOnly, // preferences readOnly.
}) => {
const [currentIndexesView, setCurrentIndexesView] =
useState<IndexView>('regular-indexes');

const deleteIndex = (index: IndexDefinition) => {
if (index.extra.status === 'failed') {
return dropFailedIndex(String(index.extra.id));
Expand All @@ -87,17 +91,24 @@ export const Indexes: React.FunctionComponent<IndexesProps> = ({
hasTooManyIndexes={indexes.length > IDEAL_NUMBER_OF_MAX_INDEXES}
isAtlasSearchSupported={true}
onRefreshIndexes={refreshIndexes}
onChangeIndexView={setCurrentIndexesView}
/>
{!isReadonlyView && !error && (
<IndexesTable
indexes={indexes}
serverVersion={serverVersion}
canModifyIndex={isWritable && !readOnly}
onSortTable={sortIndexes}
onDeleteIndex={deleteIndex}
onHideIndex={onHideIndex}
onUnhideIndex={onUnhideIndex}
/>
{!isReadonlyView &&
!error &&
currentIndexesView === 'regular-indexes' && (
<IndexesTable
indexes={indexes}
serverVersion={serverVersion}
canModifyIndex={isWritable && !readOnly}
onSortTable={sortIndexes}
onDeleteIndex={deleteIndex}
onHideIndex={onHideIndex}
onUnhideIndex={onUnhideIndex}
/>
)}

{!isReadonlyView && !error && currentIndexesView === 'search-indexes' && (
<p style={{ textAlign: 'center' }}>In Progress feature</p>
)}
</div>
);
Expand Down

0 comments on commit c25c1e6

Please sign in to comment.