Skip to content

Commit

Permalink
[Discover - datasource selector] Add extension group title and modal (o…
Browse files Browse the repository at this point in the history
…pensearch-project#5815)

* add log explorer re-directon modal

Signed-off-by: Eric <menwe@amazon.com>

* adjustments to comments

Signed-off-by: Eric <menwe@amazon.com>

* add one missing i18n

Signed-off-by: Eric <menwe@amazon.com>

* add redirection text to group title

Signed-off-by: Eric <menwe@amazon.com>

* include changes in changelog

Signed-off-by: Eric <menwe@amazon.com>

* remove redundent title addition and unnecessary modal toggle functions

Signed-off-by: Eric <menwe@amazon.com>

* remove one comment

Signed-off-by: Eric <menwe@amazon.com>

* add i18n

Signed-off-by: Eric <menwe@amazon.com>

* add unit tests for modal

Signed-off-by: Eric <menwe@amazon.com>

* test id change

Signed-off-by: Eric <menwe@amazon.com>

* add devDependencies for tests

Signed-off-by: Eric <menwe@amazon.com>

* use open confirm api and move mock file to discover mock folder

Signed-off-by: Eric <menwe@amazon.com>

* remove unused type

Signed-off-by: Eric <menwe@amazon.com>

* remove modal for log explorer redirection

Signed-off-by: Eric <menwe@amazon.com>

* modify changelog

Signed-off-by: Eric <menwe@amazon.com>

* remove modal test

Signed-off-by: Eric <menwe@amazon.com>

* remove one modal related test

Signed-off-by: Eric <menwe@amazon.com>

---------

Signed-off-by: Eric <menwe@amazon.com>
  • Loading branch information
mengweieric authored and SuZhou-Joe committed Apr 7, 2024
1 parent 0f34d69 commit 878ada6
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 19 deletions.
10 changes: 1 addition & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Discover] Enhanced the data source selector with added sorting functionality ([#5609](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/5609))
- [Multiple Datasource] Add datasource picker component and use it in devtools and tutorial page when multiple datasource is enabled ([#5756](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5756))
- [Multiple Datasource] Add datasource picker to import saved object flyout when multiple data source is enabled ([#5781](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5781))
- [Multiple Datasource] Add interfaces to register add-on authentication method from plug-in module ([#5851](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5851))
- [Multiple Datasource] Able to Hide "Local Cluster" option from datasource DropDown ([#5827](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5827))
- [Multiple Datasource] Add api registry and allow it to be added into client config in data source plugin ([#5895](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5895))
- [Multiple Datasource] Concatenate data source name with index pattern name and change delimiter to double colon ([#5907](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5907))
- [Multiple Datasource] Refactor client and legacy client to use authentication registry ([#5881](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5881))
- [Multiple Datasource] Improved error handling for the search API when a null value is passed for the dataSourceId ([#5882](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5882))
- [Multiple Datasource] Hide/Show authentication method in multi data source plugin based on configuration ([#5916](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5916))
- [[Dynamic Configurations] Add support for dynamic application configurations ([#5855](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5855))
- [Workspace] Optional workspaces params in repository ([#5949](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5949))
- [Discover] Add extension group title to non-index data source groups to indicate log explorer redirection in discover data source selector. ([#5815](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/5815))

### 🐛 Bug Fixes

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@
"@types/react-router-dom": "^5.3.2",
"@types/react-virtualized": "^9.18.7",
"@types/recompose": "^0.30.6",
"@types/redux-mock-store": "^1.0.6",
"@types/selenium-webdriver": "^4.0.9",
"@types/semver": "^7.5.0",
"@types/sinon": "^7.0.13",
Expand Down Expand Up @@ -446,6 +447,7 @@
"react-test-renderer": "^16.12.0",
"reactcss": "1.2.3",
"redux": "^4.0.5",
"redux-mock-store": "^1.5.4",
"regenerate": "^1.4.0",
"reselect": "^4.0.0",
"resize-observer-polyfill": "^1.5.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ import { DataSourceGroup, DataSourceSelectableProps } from './types';
type DataSourceTypeKey = 'DEFAULT_INDEX_PATTERNS' | 's3glue' | 'spark';

// Mapping between datasource type and its display name.
// Temporary solution, will be removed along with refactoring of data source APIs
const DATASOURCE_TYPE_DISPLAY_NAME_MAP: Record<DataSourceTypeKey, string> = {
DEFAULT_INDEX_PATTERNS: 'Index patterns',
s3glue: 'Amazon S3',
spark: 'Spark',
DEFAULT_INDEX_PATTERNS: i18n.translate('dataExplorer.dataSourceSelector.indexPatternGroupTitle', {
defaultMessage: 'Index patterns',
}),
s3glue: i18n.translate('dataExplorer.dataSourceSelector.amazonS3GroupTitle', {
defaultMessage: 'Amazon S3',
}),
spark: i18n.translate('dataExplorer.dataSourceSelector.sparkGroupTitle', {
defaultMessage: 'Spark',
}),
};

type DataSetType = ISourceDataSet['data_sets'][number];
Expand Down Expand Up @@ -66,7 +73,19 @@ const getSourceList = (allDataSets: ISourceDataSet[]) => {
const finalList = [] as DataSourceGroup[];
allDataSets.forEach((curDataSet) => {
const typeKey = curDataSet.ds.getType() as DataSourceTypeKey;
const groupName = DATASOURCE_TYPE_DISPLAY_NAME_MAP[typeKey] || 'Default Group';
let groupName =
DATASOURCE_TYPE_DISPLAY_NAME_MAP[typeKey] ||
i18n.translate('dataExplorer.dataSourceSelector.defaultGroupTitle', {
defaultMessage: 'Default Group',
});

// add '- Opens in Log Explorer' to hint user that selecting these types of data sources
// will lead to redirection to log explorer
if (typeKey !== 'DEFAULT_INDEX_PATTERNS') {
groupName = `${groupName}${i18n.translate('dataExplorer.dataSourceSelector.redirectionHint', {
defaultMessage: ' - Opens in Log Explorer',
})}`;
}

const existingGroup = finalList.find((item) => item.label === groupName);
const mappedOptions = curDataSet.data_sets.map((dataSet) =>
Expand Down
110 changes: 110 additions & 0 deletions src/plugins/data_explorer/public/components/sidebar/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { Sidebar } from './index'; // Adjust the import path as necessary
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import { MockS3DataSource } from '../../../../discover/public/__mock__/index.test.mock';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';

const mockStore = configureMockStore();
const initialState = {
metadata: { indexPattern: 'some-index-pattern-id' },
};
const store = mockStore(initialState);

jest.mock('../../../../opensearch_dashboards_react/public', () => {
return {
toMountPoint: jest.fn().mockImplementation((component) => () => component),
useOpenSearchDashboards: jest.fn().mockReturnValue({
services: {
data: {
indexPatterns: {},
dataSources: {
dataSourceService: {
dataSources$: {
subscribe: jest.fn((callback) => {
callback({
's3-prod-mock': new MockS3DataSource({
name: 's3-prod-mock',
type: 's3glue',
metadata: {},
}),
});
return { unsubscribe: jest.fn() };
}),
},
},
},
},
notifications: {
toasts: {
addError: jest.fn(),
},
},
application: {
navigateToUrl: jest.fn(),
},
overlays: {
openConfirm: jest.fn(),
},
},
}),
withOpenSearchDashboards: () => (Component: React.ComponentClass) => (props: any) => (
<Component {...props} />
),
};
});

jest.mock('../../../../data_explorer/public', () => ({
useTypedSelector: jest.fn(),
useTypedDispatch: jest.fn(),
}));

describe('Sidebar Component', () => {
it('renders without crashing', () => {
const { container, getByTestId } = render(
<Provider store={store}>
<Sidebar />
</Provider>
);
expect(container).toBeInTheDocument();
expect(getByTestId('dataExplorerDSSelect')).toBeInTheDocument();
});

it('shows title extensions on the non-index pattern data source', () => {
const { getByText, getByTestId } = render(
<Provider store={store}>
<Sidebar />
</Provider>
);

fireEvent.click(getByTestId('comboBoxToggleListButton'));
waitFor(() => {
expect(getByText('Open in Log Explorer')).toBeInTheDocument();
});
});

it('redirects to log explorer when clicking open-in-log-explorer button', () => {
const history = createMemoryHistory();
const { getByText, getByTestId } = render(
<Provider store={store}>
<Router history={history}>
<Sidebar />
</Router>
</Provider>
);

fireEvent.click(getByTestId('comboBoxToggleListButton'));
waitFor(() => {
expect(getByText('s3-prod-mock')).toBeInTheDocument();
fireEvent.click(getByText('s3-prod-mock'));
expect(history.location.pathname).toContain('observability-logs#/explorer');
});
});
});
20 changes: 14 additions & 6 deletions src/plugins/data_explorer/public/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,31 @@ export const Sidebar: FC = ({ children }) => {
}
}, [indexPatternId, activeDataSources, dataSourceOptionList]);

const redirectToLogExplorer = useCallback(
(dsName: string, dsType: string) => {
return application.navigateToUrl(
`../observability-logs#/explorer?datasourceName=${dsName}&datasourceType=${dsType}`
);
},
[application]
);

const handleSourceSelection = useCallback(
(selectedDataSources: DataSourceOption[]) => {
if (selectedDataSources.length === 0) {
setSelectedSources(selectedDataSources);
return;
}
// Temporary redirection solution for 2.11, where clicking non-index-pattern datasource
// will redirect user to Observability event explorer
// Temporary redirection solution for 2.11, where clicking non-index-pattern data sources
// will prompt users with modal explaining they are being redirected to Observability log explorer
if (selectedDataSources[0]?.ds?.getType() !== 'DEFAULT_INDEX_PATTERNS') {
return application.navigateToUrl(
`../observability-logs#/explorer?datasourceName=${selectedDataSources[0].label}&datasourceType=${selectedDataSources[0].type}`
);
redirectToLogExplorer(selectedDataSources[0].label, selectedDataSources[0].type);
return;
}
setSelectedSources(selectedDataSources);
dispatch(setIndexPattern(selectedDataSources[0].value));
},
[application, dispatch]
[dispatch, redirectToLogExplorer, setSelectedSources]
);

const handleGetDataSetError = useCallback(
Expand Down
28 changes: 28 additions & 0 deletions src/plugins/discover/public/__mock__/index.test.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export class MockS3DataSource {
protected name: string;
protected type: string;
protected metadata: any;

constructor({ name, type, metadata }: { name: string; type: string; metadata: any }) {
this.name = name;
this.type = type;
this.metadata = metadata;
}

async getDataSet(dataSetParams?: any) {
return [this.name];
}

getName() {
return this.name;
}

getType() {
return this.type;
}
}
14 changes: 14 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3904,6 +3904,13 @@
dependencies:
"@types/react" "*"

"@types/redux-mock-store@^1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.6.tgz#0a03b2655028b7cf62670d41ac1de5ca1b1f5958"
integrity sha512-eg5RDfhJTXuoJjOMyXiJbaDb1B8tfTaJixscmu+jOusj6adGC0Krntz09Tf4gJgXeCqCrM5bBMd+B7ez0izcAQ==
dependencies:
redux "^4.0.5"

"@types/refractor@^3.0.0":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/refractor/-/refractor-3.0.2.tgz#2d42128d59f78f84d2c799ffc5ab5cadbcba2d82"
Expand Down Expand Up @@ -15452,6 +15459,13 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"

redux-mock-store@^1.5.4:
version "1.5.4"
resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.4.tgz#90d02495fd918ddbaa96b83aef626287c9ab5872"
integrity sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==
dependencies:
lodash.isplainobject "^4.0.6"

redux-thunk@^2.3.0, redux-thunk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714"
Expand Down

0 comments on commit 878ada6

Please sign in to comment.