Skip to content

Commit

Permalink
Add column service to index pattern & Register data source column (op…
Browse files Browse the repository at this point in the history
…ensearch-project#2542)

Signed-off-by: Kristen Tian <tyarong@amazon.com>

Signed-off-by: Kristen Tian <tyarong@amazon.com>
Signed-off-by: Sergey V. Osipov <sipopo@yandex.ru>
  • Loading branch information
kristenTian authored and sipopo committed Dec 16, 2022
1 parent 3bfabf4 commit 3696483
Show file tree
Hide file tree
Showing 16 changed files with 193 additions and 16 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* [MD] Support legacy client for data source ([#2204](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2204))
* [Plugin Helpers] Facilitate version changes ([#2398](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2398))
* [MD] Display error toast for create index pattern with data source ([#2506](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2506))
* [Multi DataSource] UX enhacement on index pattern management stack ([#2505](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2505))
* [Multi DataSource] UX enhancement on index pattern management stack ([#2505](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2505))
* [Multi DataSource] UX enhancement on Data source management stack ([#2521](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2521))
* [Multi DataSource] UX enhancement on Index Pattern management stack ([#2527](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2527))
* [Multi DataSource] Add data source column into index pattern table ([#2542](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2542))

### 🐛 Bug Fixes
* [Vis Builder] Fixes auto bounds for timeseries bar chart visualization ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401))
* [Vis Builder] Fixes visualization shift when editing agg ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401))
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/data_source/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { DataSourcePublicPlugin } from './plugin';
import { DataSourcePlugin } from './plugin';

// This exports static code and TypeScript types,
// as well as, OpenSearch Dashboards Platform `plugin()` initializer.
export function plugin() {
return new DataSourcePublicPlugin();
return new DataSourcePlugin();
}

export { DataSourcePublicPluginSetup, DataSourcePublicPluginStart } from './types';
export { DataSourcePluginSetup, DataSourcePluginStart } from './types';
9 changes: 4 additions & 5 deletions src/plugins/data_source/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
*/

import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { DataSourcePublicPluginSetup, DataSourcePublicPluginStart } from './types';
import { DataSourcePluginSetup, DataSourcePluginStart } from './types';

export class DataSourcePublicPlugin
implements Plugin<DataSourcePublicPluginSetup, DataSourcePublicPluginStart> {
public setup(core: CoreSetup): DataSourcePublicPluginSetup {
export class DataSourcePlugin implements Plugin<DataSourcePluginSetup, DataSourcePluginStart> {
public setup(core: CoreSetup): DataSourcePluginSetup {
return {};
}

public start(core: CoreStart): DataSourcePublicPluginStart {
public start(core: CoreStart): DataSourcePluginStart {
return {};
}

Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data_source/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataSourcePublicPluginSetup {}
export interface DataSourcePluginSetup {}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface DataSourcePublicPluginStart {}
export interface DataSourcePluginStart {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "opensearchDashboards",
"server": false,
"ui": true,
"requiredPlugins": ["management", "dataSource"],
"requiredPlugins": ["management", "dataSource", "indexPatternManagement"],
"optionalPlugins": [],
"requiredBundles": ["opensearchDashboardsReact"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { i18n } from '@osd/i18n';
import { HttpStart, SavedObjectsStart } from 'opensearch-dashboards/public';
import { EuiBadge, EuiLink } from '@elastic/eui';
import React from 'react';
import {
IndexPatternTableColumn,
IndexPatternTableRecord,
} from '../../../../index_pattern_management/public';
import { getDataSources } from '../utils';
import { DataSourceTableItem } from '../../types';

type DataSourceColumnItem = DataSourceTableItem & { relativeUrl: string };
type DataSourceMap = Map<string, DataSourceColumnItem> | undefined;

export class DataSourceColumn implements IndexPatternTableColumn<DataSourceMap> {
public readonly id: string = 'data_source';
public data: DataSourceMap;

public euiColumn = {
field: 'referenceId',
name: i18n.translate('dataSource.management.dataSourceColumn', {
defaultMessage: 'Data Source',
}),
render: (referenceId: string, index: IndexPatternTableRecord) => {
if (!referenceId) {
return null;
}

const dataSource = this.data?.get(referenceId);
if (!dataSource) {
// Index pattern has the referenceId but data source not found.
return <EuiBadge color="danger">Deleted</EuiBadge>;
}

const { title, relativeUrl } = dataSource;
return <EuiLink href={relativeUrl}>{title}</EuiLink>;
},
};

constructor(
private readonly savedObjectPromise: Promise<SavedObjectsStart>,
private readonly httpPromise: Promise<HttpStart>
) {}

public loadData = async () => {
const savedObject = await this.savedObjectPromise;
const { basePath } = await this.httpPromise;

return getDataSources(savedObject.client).then((dataSources?: DataSourceTableItem[]) => {
this.data = dataSources
?.map((dataSource) => {
return {
...dataSource,
relativeUrl: basePath.prepend(
`/app/management/opensearch-dashboards/dataSources/${encodeURIComponent(
dataSource.id
)}`
),
};
})
?.reduce(
(map, dataSource) => map.set(dataSource.id, dataSource),
new Map<string, DataSourceColumnItem>()
);
return this.data;
});
};
}
15 changes: 14 additions & 1 deletion src/plugins/data_source_management/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,35 @@ import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { PLUGIN_NAME } from '../common';

import { ManagementSetup } from '../../management/public';
import { IndexPatternManagementSetup } from '../../index_pattern_management/public';
import { DataSourceColumn } from './components/data_source_column/data_source_column';

export interface DataSourceManagementSetupDependencies {
management: ManagementSetup;
indexPatternManagement: IndexPatternManagementSetup;
}

const DSM_APP_ID = 'dataSources';

export class DataSourceManagementPlugin
implements Plugin<void, void, DataSourceManagementSetupDependencies> {
public setup(core: CoreSetup, { management }: DataSourceManagementSetupDependencies) {
public setup(
core: CoreSetup,
{ management, indexPatternManagement }: DataSourceManagementSetupDependencies
) {
const opensearchDashboardsSection = management.sections.section.opensearchDashboards;

if (!opensearchDashboardsSection) {
throw new Error('`opensearchDashboards` management section not found.');
}

const savedObjectPromise = core
.getStartServices()
.then(([coreStart]) => coreStart.savedObjects);
const httpPromise = core.getStartServices().then(([coreStart]) => coreStart.http);
const column = new DataSourceColumn(savedObjectPromise, httpPromise);
indexPatternManagement.columns.register(column);

opensearchDashboardsSection.registerApp({
id: DSM_APP_ID,
title: PLUGIN_NAME,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import { FormattedMessage } from '@osd/i18n/react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import React, { useState, useEffect } from 'react';
import { i18n } from '@osd/i18n';
import { useMount } from 'react-use';
import { useEffectOnce, useMount } from 'react-use';
import {
reactRouterNavigate,
useOpenSearchDashboards,
Expand Down Expand Up @@ -112,6 +112,9 @@ export const IndexPatternTable = ({ canSave, history }: Props) => {
const [remoteClustersExist, setRemoteClustersExist] = useState<boolean>(false);
const [isLoadingSources, setIsLoadingSources] = useState<boolean>(!dataSourceEnabled);
const [isLoadingIndexPatterns, setIsLoadingIndexPatterns] = useState<boolean>(true);
const [isColumnDataLoaded, setIsColumnDataLoaded] = useState(false);

const { columns: columnRegistry } = indexPatternManagementStart;

useMount(() => {
setBreadcrumbs(getListBreadcrumbs());
Expand Down Expand Up @@ -153,6 +156,11 @@ export const IndexPatternTable = ({ canSave, history }: Props) => {
);
};

const loadColumnData = async () => {
await Promise.all(columnRegistry.getAll().map((column) => column.loadData()));
setIsColumnDataLoaded(true);
};

useEffect(() => {
if (!dataSourceEnabled) {
getIndices({ http, pattern: '*', searchClient }).then((dataSources) => {
Expand All @@ -165,6 +173,10 @@ export const IndexPatternTable = ({ canSave, history }: Props) => {
}
}, [http, creationOptions, searchClient, dataSourceEnabled]);

useEffectOnce(() => {
loadColumnData();
});

chrome.docTitle.change(title);

const columns = [
Expand Down Expand Up @@ -197,6 +209,13 @@ export const IndexPatternTable = ({ canSave, history }: Props) => {
dataType: 'string' as const,
sortable: ({ sort }: { sort: string }) => sort,
},
...columnRegistry.getAll().map((column) => {
return {
...column.euiColumn,
sortable: false,
'data-test-subj': `indexPatternTableColumn-${column.id}`,
};
}),
];

const createButton = canSave ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,22 @@ export async function getIndexPatterns(
.map((pattern) => {
const id = pattern.id;
const title = pattern.get('title');
const references = pattern.references;
const isDefault = defaultIndex === id;

const tags = (indexPatternManagementStart as IndexPatternManagementStart).list.getIndexPatternTags(
pattern,
isDefault
);
const reference = Array.isArray(references) ? references[0] : undefined;
const referenceId = reference?.id;

return {
id,
title,
default: isDefault,
tags,
referenceId,
// the prepending of 0 at the default pattern takes care of prioritization
// so the sorting will but the default index on top
// or on bottom of a the table
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/index_pattern_management/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ export {

export { DefaultFormatEditor } from './components/field_editor/components/field_format_editor';

export { MlCardState } from './types';
export { MlCardState, IndexPatternTableColumn, IndexPatternTableRecord } from './types';
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import { i18n } from '@osd/i18n';
import { I18nProvider } from '@osd/i18n/react';
import { StartServicesAccessor } from 'src/core/public';

import { EuiIconType } from '@elastic/eui/src/components/icon/icon';
import { OpenSearchDashboardsContextProvider } from '../../../opensearch_dashboards_react/public';
import { ManagementAppMountParams } from '../../../management/public';
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { IndexPatternTableColumn } from '../../types';

export interface IndexPatternTableColumnServiceSetup {
/**
* register given column in the registry.
*/
register: (column: IndexPatternTableColumn<unknown>) => void;
}

export interface IndexPatternTableColumnServiceStart {
/**
* return all {@link IndexPatternTableColumn | columns} currently registered.
*/
getAll: () => Array<IndexPatternTableColumn<unknown>>;
}

export class IndexPatternTableColumnService {
private readonly columns = new Map<string, IndexPatternTableColumn<unknown>>();

setup(): IndexPatternTableColumnServiceSetup {
return {
register: (column) => {
if (this.columns.has(column.id)) {
throw new Error(`Index Pattern Table Column with id '${column.id}' already exists`);
}
this.columns.set(column.id, column);
},
};
}

start(): IndexPatternTableColumnServiceStart {
return {
getAll: () => [...this.columns.values()],
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './column_service';
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
TruncateFormatEditor,
UrlFormatEditor,
} from '../components/field_editor/components/field_format_editor';
import { IndexPatternTableColumnService } from './column_service';

interface SetupDependencies {
httpClient: HttpSetup;
Expand All @@ -62,12 +63,14 @@ export class IndexPatternManagementService {
indexPatternListConfig: IndexPatternListManager;
fieldFormatEditors: FieldFormatEditors;
environmentService: EnvironmentService;
columnService: IndexPatternTableColumnService;

constructor() {
this.indexPatternCreationManager = new IndexPatternCreationManager();
this.indexPatternListConfig = new IndexPatternListManager();
this.fieldFormatEditors = new FieldFormatEditors();
this.environmentService = new EnvironmentService();
this.columnService = new IndexPatternTableColumnService();
}

public setup({ httpClient }: SetupDependencies) {
Expand Down Expand Up @@ -98,6 +101,7 @@ export class IndexPatternManagementService {
list: indexPatternListConfigSetup,
fieldFormatEditors: fieldFormatEditorsSetup,
environment: this.environmentService.setup(),
columns: this.columnService.setup(),
};
}

Expand All @@ -106,6 +110,7 @@ export class IndexPatternManagementService {
creation: this.indexPatternCreationManager.start(),
list: this.indexPatternListConfig.start(),
fieldFormatEditors: this.fieldFormatEditors.start(),
columns: this.columnService.start(),
};
}

Expand Down
Loading

0 comments on commit 3696483

Please sign in to comment.