Skip to content

Commit

Permalink
needs to set the source
Browse files Browse the repository at this point in the history
Signed-off-by: Kawika Avilla <kavilla414@gmail.com>
  • Loading branch information
kavilla committed Jul 21, 2024
1 parent 7f9bdd7 commit 7cbe1e0
Show file tree
Hide file tree
Showing 32 changed files with 593 additions and 238 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/7289.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Add DataSet dropdown with index patterns and indices ([#7289](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7289))
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
"start": "scripts/use_node scripts/opensearch_dashboards --dev",
"start:docker": "scripts/use_node scripts/opensearch_dashboards --dev --opensearch.hosts=$OPENSEARCH_HOSTS --opensearch.ignoreVersionMismatch=true --server.host=$SERVER_HOST",
"start:security": "scripts/use_node scripts/opensearch_dashboards --dev --security",
"start:enhancements": "scripts/use_node scripts/opensearch_dashboards --dev --uiSettings.overrides['query:enhancements:enabled']=true",
"start:enhancements": "scripts/use_node scripts/opensearch_dashboards --dev --uiSettings.overrides['query:enhancements:enabled']=true --uiSettings.overrides['home:useNewHomePage']=true",
"debug": "scripts/use_node --nolazy --inspect scripts/opensearch_dashboards --dev",
"debug-break": "scripts/use_node --nolazy --inspect-brk scripts/opensearch_dashboards --dev",
"lint": "yarn run lint:es && yarn run lint:style",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { SavedObjectsClientContract } from 'src/core/public';
import { DataSetNavigator, DataSetNavigatorProps } from './';

// Updated function signature to include additional dependencies
export function createDataSetNavigator(savedObjectsClient: SavedObjectsClientContract) {
// Return a function that takes props, omitting the dependencies from the props type
return (props: Omit<DataSetNavigatorProps, 'savedObjectsClient'>) => (
<DataSetNavigator {...props} savedObjectsClient={savedObjectsClient} />
);
}
223 changes: 223 additions & 0 deletions src/plugins/data/public/ui/dataset_navigator/dataset_navigator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { Component } from 'react';
import { EuiButtonEmpty, EuiContextMenu, EuiPopover } from '@elastic/eui';
import { SavedObjectsClientContract } from 'opensearch-dashboards/public';
import _ from 'lodash';
import { i18n } from '@osd/i18n';
import { fetchClusters } from './fetch_clusters';
import { fetchIndices } from './fetch_indices';
import { getSearchService } from '../../services';
import { fetchIndexPatterns } from './fetch_index_patterns';

export interface DataSetOption {
id: string;
name?: string;
dataSourceRef?: string;
}

export interface DataSetNavigatorProps {
dataSetId: string | undefined;
savedObjectsClient?: SavedObjectsClientContract;
onSelectDataSet: (dataSet: any) => void;
}

interface DataSetNavigatorState {
isLoading: boolean;
indexPatterns?: any; // Array<IIndexPattern | string>;
dataSources: any[];
externalDataSources: [];
searchValue: string | undefined;
isOpen: boolean;
selectedDataSet: any;
selectedDataSource?: any;
}

// eslint-disable-next-line import/no-default-export
export default class DataSetNavigator extends Component<DataSetNavigatorProps> {
private isMounted: boolean = false;
state: DataSetNavigatorState;
private search = getSearchService();

constructor(props: DataSetNavigatorProps) {
super(props);
this.state = {
isLoading: false,
indexPatterns: [],
dataSources: [],
externalDataSources: [],
searchValue: undefined,
isOpen: false,
selectedDataSource: undefined,
selectedDataSet: undefined,
};

this.fetchIndexPatterns();
this.fetchDataSources();
}

componentDidMount() {
this.isMounted = true;
}

// componentDidUpdate(
// prevProps: { savedObjectsClient: SavedObjectsClientContract },
// prevState: { selectedCluster: any }
// ) {
// if (
// this.props.savedObjectsClient !== prevProps.savedObjectsClient ||
// this.state.selectedCluster !== prevState.selectedCluster
// ) {
// if (this.state.selectedCluster) {
// this.fetchIndices();
// }
// }
// }

componentWillUnmount() {
this.isMounted = false;
}

fetchIndexPatterns = async () => {
const res = await fetchIndexPatterns(this.props.savedObjectsClient!, '', ['title']);
if (this.isMounted) {
this.setState({ indexPatterns: res });
if (!this.state.selectedDataSet && this.props.dataSetId) {
const matchingIndexPattern = res.find((pattern) => pattern.id === this.props.dataSetId);
if (matchingIndexPattern) {
this.setState({ selectedDataSet: matchingIndexPattern });
}
}
}
};

fetchDataSources = async () => {
const res = await fetchClusters(this.props.savedObjectsClient!);
if (this.isMounted) {
this.setState({ dataSources: res.savedObjects });
}
};

fetchIndices = async (dataSource: any) => {
const res = await fetchIndices(this.search, dataSource.id); // .id);
const updatedRes = res.map((index: any) => ({
...index,
dataSourceRef: dataSource.id,
}));
if (this.isMounted) {
this.setState({ selectedDataSource: { ...dataSource, indexList: updatedRes } });
}
};

handleDataSetChange = (dataSource: any, dataSet: any) => {
const dataSetTitle =
typeof dataSet === 'string' ? dataSet : dataSet.name ?? dataSet.attributes.title;
const selectedDataSet = dataSource
? `${dataSource.attributes.title}::${dataSetTitle}`
: dataSetTitle;
this.setState({ selectedDataSet });
this.props.onSelectDataSet(dataSet);
this.closePopover();
};

onButtonClick = () => {
this.setState({ isOpen: !this.state.isOpen });
};

closePopover = () => {
this.setState({ isOpen: false });
};

render() {
const {
isOpen,
indexPatterns,
selectedDataSet,
selectedDataSource,
dataSources,
externalDataSources,
} = this.state;
const indexPatternsLabel = i18n.translate('data.query.dataSetNavigator.indexPatternsName', {
defaultMessage: 'Index Patterns',
});
const dataSourceLabel = i18n.translate('data.query.dataSetNavigator.dataSourceLabel', {
defaultMessage: 'DataSource',
});
return (
<EuiPopover
button={
<EuiButtonEmpty
className="dataExplorerDSSelect"
color="text"
iconType="arrowDown"
iconSide="right"
onClick={this.onButtonClick}
>
{typeof selectedDataSet === 'string'
? selectedDataSet
: selectedDataSet?.attributes?.title ?? 'Select a DataSet'}
</EuiButtonEmpty>
}
isOpen={isOpen}
closePopover={this.closePopover}
anchorPosition="downLeft"
>
<EuiContextMenu
initialPanelId={0}
className="dataSetNavigator"
panels={[
{
id: 0,
title: 'DATA',
items: [
{
name: indexPatternsLabel,
panel: 1,
},
...dataSources.map((dataSource) => ({
name: dataSource.attributes.title,
panel: 2,
onClick: () => {
this.fetchIndices(dataSource);
},
})),
],
},
{
id: 1,
title: indexPatternsLabel,
items: indexPatterns!.map((indexPattern: any) => ({
name: indexPattern.attributes.title,
onClick: () => {
this.handleDataSetChange(null, indexPattern);
},
})),
},
{
id: 2,
title: selectedDataSource?.title,
items: [
{
name: 'Indexes',
panel: 3,
},
],
},
{
id: 3,
items: selectedDataSource?.indexList.map((index: any) => ({
name: index.name,
onClick: async () => {
this.handleDataSetChange(selectedDataSource, index);
},
})),
},
]}
/>
</EuiPopover>
);
}
}
13 changes: 13 additions & 0 deletions src/plugins/data/public/ui/dataset_navigator/fetch_clusters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { SavedObjectsClientContract } from 'opensearch-dashboards/public';

export const fetchClusters = async (savedObjectsClient: SavedObjectsClientContract) => {
return await savedObjectsClient.find({
type: 'data-source',
perPage: 10000,
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { SavedObjectsClientContract } from 'opensearch-dashboards/public';

export const fetchIndexPatterns = async (
client: SavedObjectsClientContract,
search: string,
fields: string[]
) => {
const resp = await client.find({
type: 'index-pattern',
fields,
search: `${search}*`,
searchFields: ['title'],
perPage: 100,
});
return resp.savedObjects;
};
67 changes: 67 additions & 0 deletions src/plugins/data/public/ui/dataset_navigator/fetch_indices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { map, scan } from 'rxjs/operators';
import { ISearchStart } from '../../search';

export const fetchIndices = async (search: ISearchStart, dataSourceId: string) => {
const request = buildSearchRequest(true, '*', dataSourceId);
return search
.getDefaultSearchInterceptor()
.search(request)
.pipe(map(searchResponseToArray(true)))
.pipe(scan((accumulator = [], value) => accumulator.join(value)))
.toPromise()
.catch(() => []);
};

const searchResponseToArray = (showAllIndices: boolean) => (response) => {
const { rawResponse } = response;
if (!rawResponse.aggregations) {
return [];
} else {
return rawResponse.aggregations.indices.buckets
.map((bucket: { key: string }) => {
return bucket.key;
})
.filter((indexName: string) => {
if (showAllIndices) {
return true;
} else {
return !indexName.startsWith('.');
}
})
.map((indexName: string) => {
return {
name: indexName,
// item: {},
};
});
}
};

const buildSearchRequest = (showAllIndices: boolean, pattern: string, dataSourceId?: string) => {
const request = {
params: {
ignoreUnavailable: true,
expand_wildcards: showAllIndices ? 'all' : 'open',
index: pattern,
body: {
size: 0, // no hits
aggs: {
indices: {
terms: {
field: '_index',
size: 100,
},
},
},
},
},
dataSourceId,
};

return request;
};
23 changes: 23 additions & 0 deletions src/plugins/data/public/ui/dataset_navigator/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import type { DataSetNavigatorProps } from './dataset_navigator';

const Fallback = () => <div />;

const LazyDataSetNavigator = React.lazy(() => import('./dataset_navigator'));
export const DataSetNavigator = (props: DataSetNavigatorProps) => (
<React.Suspense fallback={<Fallback />}>
<LazyDataSetNavigator {...props} />
</React.Suspense>
);

export * from './create_dataset_navigator';
export type { DataSetNavigatorProps } from './dataset_navigator';

export { fetchClusters } from './fetch_clusters';
export { fetchIndexPatterns } from './fetch_index_patterns';
export { fetchIndices } from './fetch_indices';
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './create_extension';
.dataSetNavigator {
width: 350px;
border-bottom: $euiBorderThin !important;
}
1 change: 1 addition & 0 deletions src/plugins/data/public/ui/query_editor/_index.scss
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@import "./language_selector";
@import "./dataset_navigator";
@import "./query_editor";
Loading

0 comments on commit 7cbe1e0

Please sign in to comment.