diff --git a/CHANGELOG.md b/CHANGELOG.md index 837e7b7453bd..d2e98020e871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * [Multi DataSource] UX enhancement for Data source management creation page ([#2051](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2501)) * [Multi DataSource] Add experimental callout for index pattern section ([#2523](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2523)) * [Multi DataSource] Add data source config to opensearch-dashboards-docker ([#2557](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2557)) +* [Multi DataSource] Make text content dynamically translated & update unit tests ([#2570](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2570)) ### 🐛 Bug Fixes * [Vis Builder] Fixes auto bounds for timeseries bar chart visualization ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401)) diff --git a/src/plugins/data_source_management/public/components/create_button/__snapshots__/create_button.test.tsx.snap b/src/plugins/data_source_management/public/components/create_button/__snapshots__/create_button.test.tsx.snap index ce57668cd417..f0e2965c6678 100644 --- a/src/plugins/data_source_management/public/components/create_button/__snapshots__/create_button.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/create_button/__snapshots__/create_button.test.tsx.snap @@ -6,6 +6,10 @@ exports[`CreateButton should render normally 1`] = ` fill={true} onClick={[Function]} > - Create data source connection + `; diff --git a/src/plugins/data_source_management/public/components/create_button/create_button.tsx b/src/plugins/data_source_management/public/components/create_button/create_button.tsx index b02d3716cbf5..072eb8af6029 100644 --- a/src/plugins/data_source_management/public/components/create_button/create_button.tsx +++ b/src/plugins/data_source_management/public/components/create_button/create_button.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { History } from 'history'; import { EuiButton } from '@elastic/eui'; -import { CREATE_DATA_SOURCE_BUTTON_TEXT } from '../text_content'; +import { FormattedMessage } from '@osd/i18n/react'; interface Props { history: History; @@ -20,7 +20,10 @@ export const CreateButton = ({ history }: Props) => { fill={true} onClick={() => history.push('/create')} > - {CREATE_DATA_SOURCE_BUTTON_TEXT} + ); }; diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/__snapshots__/create_data_source_wizard.test.tsx.snap b/src/plugins/data_source_management/public/components/create_data_source_wizard/__snapshots__/create_data_source_wizard.test.tsx.snap index 16215de8d86a..a7c32d540d27 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/__snapshots__/create_data_source_wizard.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/__snapshots__/create_data_source_wizard.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Datasource Management: Create Datasource Wizard should render normally 1`] = ` +exports[`Datasource Management: Create Datasource Wizard case1: should load resources successfully should render normally 1`] = ` @@ -70,7 +70,982 @@ exports[`Datasource Management: Create Datasource Wizard should render normally className="euiTitle euiTitle--medium" data-test-subj="createDataSourceHeader" > - Create data source connection + + + Create data source connection + + + + + +
+ + +
+

+ + + Create a new data source connection to help you retrieve data from an external OpenSearch compatible source. + + +
+

+
+
+
+ + + + + + +
+ +
+

+ + + Connection Details + + +

+
+
+ +
+ + +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ + + + + - + + + + + } + labelType="label" + > +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ +
+ + +
+

+ + + Authentication Method + + +

+
+
+ +
+ + +
+
+ +
+ + + Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + + + + + No authentication + + + +
+
+
+
+
+ +
+ + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+
+ + +
+
+ + + +
+
+ + +
+
+ + + + +
+
+
+
+
+
+
+ +
+
+ + + +
+
+ + , + ] + } + compressed={false} + fullWidth={false} + icon="lock" + isLoading={false} + > +
+
+ + + + +
+ + + + + +
+
+
+ + + +
+
+
+
+
+
+ +
+ + + + + + +
+ +
+ + + + + +`; + +exports[`Datasource Management: Create Datasource Wizard case2: should fail to load resources should not render component and go back to listing page 1`] = ` + + + + + +
+
+ +
+ +
+
+ +

+ + + Create data source connection + +

- Description + - - - optional + - + + } @@ -261,7 +1245,15 @@ exports[`Datasource Management: Create Datasource Wizard should render normally className="euiFormLabel euiFormRow__label" htmlFor="generated-id" > - Description + + + Description + + - - - optional + - + + + + optional + + @@ -463,9 +1464,25 @@ exports[`Datasource Management: Create Datasource Wizard should render normally onBlur={[Function]} onFocus={[Function]} > - Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + + Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + - No authentication + + + No authentication + +
@@ -880,7 +1897,15 @@ exports[`Datasource Management: Create Datasource Wizard should render normally - Create data source connection + + + Create data source connection + + diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/__snapshots__/create_data_source_form.test.tsx.snap b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/__snapshots__/create_data_source_form.test.tsx.snap index 8549619e7d71..1006968b632f 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/__snapshots__/create_data_source_form.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/__snapshots__/create_data_source_form.test.tsx.snap @@ -5,7 +5,11 @@ exports[`Datasource Management: Create Datasource form should create data source locale="en" > - Create data source connection + + + Create data source connection + + - Description + - - - optional + - + + } @@ -285,7 +306,15 @@ exports[`Datasource Management: Create Datasource form should create data source className="euiFormLabel euiFormRow__label" htmlFor="generated-id" > - Description + + + Description + + - - - optional + - + + + + optional + + @@ -487,9 +525,25 @@ exports[`Datasource Management: Create Datasource form should create data source onBlur={[Function]} onFocus={[Function]} > - Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + + Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + - No authentication + + + No authentication + +
@@ -663,7 +717,15 @@ exports[`Datasource Management: Create Datasource form should create data source - Create data source connection + + + Create data source connection + + @@ -684,7 +746,11 @@ exports[`Datasource Management: Create Datasource form should create data source locale="en" > - Create data source connection + + + Create data source connection + + - Description + - - - optional + - + + } @@ -950,7 +1033,15 @@ exports[`Datasource Management: Create Datasource form should create data source className="euiFormLabel euiFormRow__label" htmlFor="generated-id" > - Description + + + Description + + - - - optional + - + + + + optional + + @@ -1152,9 +1252,25 @@ exports[`Datasource Management: Create Datasource form should create data source onBlur={[Function]} onFocus={[Function]} > - Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + + Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + - No authentication + + + No authentication + +
@@ -1569,7 +1685,15 @@ exports[`Datasource Management: Create Datasource form should create data source - Create data source connection + + + Create data source connection + + @@ -1590,7 +1714,11 @@ exports[`Datasource Management: Create Datasource form should render normally 1` locale="en" > @@ -1622,7 +1750,15 @@ exports[`Datasource Management: Create Datasource form should render normally 1` className="euiTitle euiTitle--medium" data-test-subj="createDataSourceHeader" > - Create data source connection + + + Create data source connection + + - Description + - - - optional + - + + } @@ -1813,7 +1958,15 @@ exports[`Datasource Management: Create Datasource form should render normally 1` className="euiFormLabel euiFormRow__label" htmlFor="generated-id" > - Description + + + Description + + - - - optional + - + + + + optional + + @@ -2015,9 +2177,25 @@ exports[`Datasource Management: Create Datasource form should render normally 1` onBlur={[Function]} onFocus={[Function]} > - Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + + Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + - No authentication + + + No authentication + +
@@ -2432,7 +2610,15 @@ exports[`Datasource Management: Create Datasource form should render normally 1` - Create data source connection + + + Create data source connection + + @@ -2453,7 +2639,11 @@ exports[`Datasource Management: Create Datasource form should throw validation e locale="en" > @@ -2485,7 +2675,15 @@ exports[`Datasource Management: Create Datasource form should throw validation e className="euiTitle euiTitle--medium" data-test-subj="createDataSourceHeader" > - Create data source connection + + + Create data source connection + + - Description + - - - optional + - + + } @@ -2693,7 +2900,15 @@ exports[`Datasource Management: Create Datasource form should throw validation e className="euiFormLabel euiFormRow__label" htmlFor="generated-id" > - Description + + + Description + + - - - optional + - + + + + optional + + @@ -2895,9 +3119,25 @@ exports[`Datasource Management: Create Datasource form should throw validation e onBlur={[Function]} onFocus={[Function]} > - Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + + Provide authentication details require to gain access to the endpoint. If no authentication is required, choose + + - No authentication + + + No authentication + +
@@ -3312,7 +3552,15 @@ exports[`Datasource Management: Create Datasource form should throw validation e - Create data source connection + + + Create data source connection + + diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx index 5daf45f947b5..5ed8370afc39 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.test.tsx @@ -44,6 +44,10 @@ describe('Datasource Management: Create Datasource form', () => { }, }); }; + const blurOnField = (testSubjId: string) => { + component.find(testSubjId).last().simulate('focus'); + component.find(testSubjId).last().simulate('blur'); + }; const setAuthTypeValue = ( comp: ReactWrapper, React.Component<{}, {}, any>>, @@ -61,7 +65,10 @@ describe('Datasource Management: Create Datasource form', () => { beforeEach(() => { component = mount( wrapWithIntl( - + ), { wrappingComponent: OpenSearchDashboardsContextProvider, @@ -154,4 +161,67 @@ describe('Datasource Management: Create Datasource form', () => { expect(component).toMatchSnapshot(); expect(mockSubmitHandler).toHaveBeenCalled(); // should call submit as all fields are valid }); + + /* Validation */ + test('should validate title as required field & no duplicates allowed', () => { + /* Validate duplicate title */ + changeTextFieldValue(titleIdentifier, 'DuP20'); + blurOnField(titleIdentifier); + // @ts-ignore + expect(component.find(titleIdentifier).first().props().isInvalid).toBe(true); + + /* change to original title */ + changeTextFieldValue(titleIdentifier, 'test_unique_value'); + blurOnField(titleIdentifier); + // @ts-ignore + expect(component.find(titleIdentifier).first().props().isInvalid).toBe(false); + }); + + test('should validate endpoint as required field & valid url', () => { + /* Validate empty endpoint */ + changeTextFieldValue(endpointIdentifier, ''); + blurOnField(endpointIdentifier); + // @ts-ignore + expect(component.find(endpointIdentifier).first().props().isInvalid).toBe(true); + + /* Validate invalid URL */ + changeTextFieldValue(endpointIdentifier, 'invalidURL'); + blurOnField(endpointIdentifier); + // @ts-ignore + expect(component.find(endpointIdentifier).first().props().isInvalid).toBe(true); + + /* Validate valid URL */ + changeTextFieldValue(endpointIdentifier, 'https://connectionurl.com'); + blurOnField(endpointIdentifier); + // @ts-ignore + expect(component.find(endpointIdentifier).first().props().isInvalid).toBe(false); + }); + + test('should validate username as required field', () => { + /* Validate empty username */ + changeTextFieldValue(usernameIdentifier, ''); + blurOnField(usernameIdentifier); + // @ts-ignore + expect(component.find(usernameIdentifier).first().props().isInvalid).toBe(true); + + /* Validate valid username */ + changeTextFieldValue(usernameIdentifier, 'admin'); + blurOnField(usernameIdentifier); + // @ts-ignore + expect(component.find(usernameIdentifier).first().props().isInvalid).toBe(false); + }); + + test('should validate password as required field', () => { + /* Validate empty password */ + changeTextFieldValue(passwordIdentifier, ''); + blurOnField(passwordIdentifier); + // @ts-ignore + expect(component.find(passwordIdentifier).first().props().isInvalid).toBe(true); + + /* Validate valid password */ + changeTextFieldValue(passwordIdentifier, 'admin123'); + blurOnField(passwordIdentifier); + // @ts-ignore + expect(component.find(passwordIdentifier).first().props().isInvalid).toBe(false); + }); }); diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx index 823e8b9ca8ae..e5d779296a58 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/create_form/create_data_source_form.tsx @@ -15,6 +15,7 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; import { FormattedMessage } from '@osd/i18n/react'; import { AuthType, @@ -31,21 +32,6 @@ import { isTitleValid, performDataSourceFormValidation, } from '../../../validation'; -import { - ENDPOINT_PLACEHOLDER, - DATA_SOURCE_DESCRIPTION_PLACEHOLDER, - DATA_SOURCE_PASSWORD_PLACEHOLDER, - USERNAME_PLACEHOLDER, - DESCRIPTION, - PASSWORD, - TITLE, - USERNAME, - ENDPOINT_URL, - OPTIONAL, - AUTHENTICATION_METHOD_DESCRIPTION, - NO_AUTHENTICATION, - CREATE_DATA_SOURCE_BUTTON_TEXT, -} from '../../../text_content'; import { isValidUrl } from '../../../utils'; export interface CreateDataSourceProps { @@ -229,10 +215,19 @@ export class CreateDataSourceForm extends React.Component< ); }; /* Render field label with Optional text*/ - renderFieldLabelAsOptional = (label: string) => { + renderFieldLabelAsOptional = (i18nId: string, defaultMessage: string) => { return ( <> - {label} - {OPTIONAL} + {}{' '} + + -{' '} + { + + } + ); }; @@ -242,12 +237,19 @@ export class CreateDataSourceForm extends React.Component< return ( <> {/* Description */} - + @@ -316,14 +342,21 @@ export class CreateDataSourceForm extends React.Component< {/* Endpoint URL */} - {AUTHENTICATION_METHOD_DESCRIPTION} - {NO_AUTHENTICATION} + + + + @@ -374,7 +415,10 @@ export class CreateDataSourceForm extends React.Component< onClick={this.onClickCreateNewDataSource} data-test-subj="createDataSourceButton" > - {CREATE_DATA_SOURCE_BUTTON_TEXT} + diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/header/header.tsx b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/header/header.tsx index 28882eb30bf3..cc8c2cf086da 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/components/header/header.tsx +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/components/header/header.tsx @@ -6,24 +6,34 @@ import React from 'react'; import { EuiSpacer, EuiTitle, EuiText, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; - +import { i18n } from '@osd/i18n'; import { FormattedMessage } from '@osd/i18n/react'; import { useOpenSearchDashboards } from '../../../../../../opensearch_dashboards_react/public'; import { DataSourceManagementContext } from '../../../../types'; -import { CREATE_DATA_SOURCE_HEADER } from '../../../text_content'; export const Header = () => { const changeTitle = useOpenSearchDashboards().services.chrome .docTitle.change; - changeTitle(CREATE_DATA_SOURCE_HEADER); + changeTitle( + i18n.translate('dataSourcesManagement.createDataSourceHeader', { + defaultMessage: 'Create data source connection', + }) + ); return (
-

{CREATE_DATA_SOURCE_HEADER}

+

+ { + + } +

diff --git a/src/plugins/data_source_management/public/components/create_data_source_wizard/create_data_source_wizard.test.tsx b/src/plugins/data_source_management/public/components/create_data_source_wizard/create_data_source_wizard.test.tsx index 7c16ec972eec..06084a41461a 100644 --- a/src/plugins/data_source_management/public/components/create_data_source_wizard/create_data_source_wizard.test.tsx +++ b/src/plugins/data_source_management/public/components/create_data_source_wizard/create_data_source_wizard.test.tsx @@ -24,51 +24,80 @@ describe('Datasource Management: Create Datasource Wizard', () => { const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); let component: ReactWrapper, React.Component<{}, {}, any>>; const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; - beforeEach(async () => { - spyOn(utils, 'getDataSources').and.returnValue(Promise.resolve(getMappedDataSources)); - await act(async () => { - component = mount( - wrapWithIntl( - - ), - { - wrappingComponent: OpenSearchDashboardsContextProvider, - wrappingComponentProps: { - services: mockedContext, - }, - } - ); + describe('case1: should load resources successfully', () => { + beforeEach(async () => { + spyOn(utils, 'getDataSources').and.returnValue(Promise.resolve(getMappedDataSources)); + await act(async () => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + }); + component.update(); }); - component.update(); - }); - test('should render normally', () => { - expect(component).toMatchSnapshot(); - }); - test('should create datasource successfully', async () => { - spyOn(utils, 'createSingleDataSource').and.returnValue({}); + test('should render normally', () => { + expect(component).toMatchSnapshot(); + }); + test('should create datasource successfully', async () => { + spyOn(utils, 'createSingleDataSource').and.returnValue({}); - await act(async () => { - // @ts-ignore - await component.find(formIdentifier).first().prop('handleSubmit')( - mockDataSourceAttributesWithAuth - ); + await act(async () => { + // @ts-ignore + await component.find(formIdentifier).first().prop('handleSubmit')( + mockDataSourceAttributesWithAuth + ); + }); + expect(utils.createSingleDataSource).toHaveBeenCalled(); + expect(history.push).toBeCalledWith(''); + }); + test('should fail to create datasource', async () => { + spyOn(utils, 'createSingleDataSource').and.throwError('error'); + await act(async () => { + // @ts-ignore + await component.find(formIdentifier).first().prop('handleSubmit')( + mockDataSourceAttributesWithAuth + ); + }); + component.update(); + expect(utils.createSingleDataSource).toHaveBeenCalled(); }); - expect(utils.createSingleDataSource).toHaveBeenCalled(); - expect(history.push).toBeCalledWith(''); }); - test('should fail to create datasource', async () => { - spyOn(utils, 'createSingleDataSource').and.throwError('error'); - await act(async () => { - // @ts-ignore - await component.find(formIdentifier).first().prop('handleSubmit')( - mockDataSourceAttributesWithAuth - ); + describe('case2: should fail to load resources', () => { + beforeEach(async () => { + spyOn(utils, 'getDataSources').and.throwError(''); + await act(async () => { + component = mount( + wrapWithIntl( + + ), + { + wrappingComponent: OpenSearchDashboardsContextProvider, + wrappingComponentProps: { + services: mockedContext, + }, + } + ); + }); + component.update(); + }); + test('should not render component and go back to listing page', () => { + expect(component).toMatchSnapshot(); + expect(history.push).toBeCalledWith(''); }); - component.update(); - expect(utils.createSingleDataSource).toHaveBeenCalled(); }); }); diff --git a/src/plugins/data_source_management/public/components/data_source_table/__snapshots__/data_source_table.test.tsx.snap b/src/plugins/data_source_management/public/components/data_source_table/__snapshots__/data_source_table.test.tsx.snap index 73118ee42b92..abd6fc95c88d 100644 --- a/src/plugins/data_source_management/public/components/data_source_table/__snapshots__/data_source_table.test.tsx.snap +++ b/src/plugins/data_source_management/public/components/data_source_table/__snapshots__/data_source_table.test.tsx.snap @@ -1,5 +1,347 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`DataSourceTable should get datasources failed should render empty table 1`] = ` + + + + +
+ +
+ +
+ +

+ + + Data Sources + + +

+
+ +
+ + +
+

+ + + Create and manage data source connections to help you retrieve data from multiple OpenSearch compatible sources. + + +

+
+
+
+ + +
+ + + + + + + +
+
+
+ + +
+ + +
+ + +
+ +
+ + + No Data Source Connections have been created yet. + + +
+
+ +
+ + + + + + + + +
+ + +
+ +
+ + + + +`; + exports[`DataSourceTable should get datasources successful should render normally 1`] = ` - Data Sources + + + Data Sources + +

- Create and manage data source connections to help you retrieve data from multiple OpenSearch compatible sources. + + + Create and manage data source connections to help you retrieve data from multiple OpenSearch compatible sources. + +

@@ -311,7 +669,15 @@ exports[`DataSourceTable should get datasources successful should render normall - Create data source connection + + + Create data source connection + + diff --git a/src/plugins/data_source_management/public/components/data_source_table/data_source_table.test.tsx b/src/plugins/data_source_management/public/components/data_source_table/data_source_table.test.tsx index cb30ffdc7a0b..cdb25c057844 100644 --- a/src/plugins/data_source_management/public/components/data_source_table/data_source_table.test.tsx +++ b/src/plugins/data_source_management/public/components/data_source_table/data_source_table.test.tsx @@ -17,9 +17,10 @@ import { getMappedDataSources, mockManagementPlugin } from '../../mocks'; const deleteButtonIdentifier = '[data-test-subj="deleteDataSourceConnections"]'; const tableIdentifier = 'EuiInMemoryTable'; -const confirmModalIndentifier = 'EuiConfirmModal'; +const confirmModalIdentifier = 'EuiConfirmModal'; const tableColumnHeaderIdentifier = 'EuiTableHeaderCell'; const tableColumnHeaderButtonIdentifier = 'EuiTableHeaderCell .euiTableHeaderButton'; +const emptyStateIdentifier = '[data-test-subj="datasourceTableEmptyState"]'; describe('DataSourceTable', () => { const mockedContext = mockManagementPlugin.createDataSourceManagementContext(); @@ -27,7 +28,7 @@ describe('DataSourceTable', () => { const history = (scopedHistoryMock.create() as unknown) as ScopedHistory; describe('should get datasources failed', () => { beforeEach(async () => { - spyOn(utils, 'getDataSources').and.returnValue(Promise.reject({})); + spyOn(utils, 'getDataSources').and.returnValue(Promise.reject()); await act(async () => { component = await mount( wrapWithIntl( @@ -45,6 +46,11 @@ describe('DataSourceTable', () => { } ); }); + component.update(); + }); + test('should render empty table', () => { + expect(component).toMatchSnapshot(); + expect(component.find(emptyStateIdentifier).exists()).toBe(true); }); }); @@ -97,7 +103,7 @@ describe('DataSourceTable', () => { expect(component.find(deleteButtonIdentifier).first().props().disabled).toBe(false); }); - it('should detele confirm modal pop up and cancel button work normally', () => { + it('should delete confirm modal pop up and cancel button work normally', () => { act(() => { // @ts-ignore component.find(tableIdentifier).props().selection.onSelectionChange(getMappedDataSources); @@ -105,17 +111,17 @@ describe('DataSourceTable', () => { component.update(); component.find(deleteButtonIdentifier).first().simulate('click'); // test if modal pop up when click the delete button - expect(component.find(confirmModalIndentifier).exists()).toBe(true); + expect(component.find(confirmModalIdentifier).exists()).toBe(true); act(() => { // @ts-ignore - component.find(confirmModalIndentifier).first().props().onCancel(); + component.find(confirmModalIdentifier).first().props().onCancel(); }); component.update(); - expect(component.find(confirmModalIndentifier).exists()).toBe(false); + expect(component.find(confirmModalIdentifier).exists()).toBe(false); }); - it('should detele confirm modal confirm button work normally', async () => { + it('should delete confirm modal confirm button work normally', async () => { spyOn(utils, 'deleteMultipleDataSources').and.returnValue(Promise.resolve({})); act(() => { @@ -124,14 +130,14 @@ describe('DataSourceTable', () => { }); component.update(); component.find(deleteButtonIdentifier).first().simulate('click'); - expect(component.find(confirmModalIndentifier).exists()).toBe(true); + expect(component.find(confirmModalIdentifier).exists()).toBe(true); await act(async () => { // @ts-ignore - await component.find(confirmModalIndentifier).first().props().onConfirm(); + await component.find(confirmModalIdentifier).first().props().onConfirm(); }); component.update(); - expect(component.find(confirmModalIndentifier).exists()).toBe(false); + expect(component.find(confirmModalIdentifier).exists()).toBe(false); }); it('should delete datasources & fail', async () => { @@ -143,16 +149,16 @@ describe('DataSourceTable', () => { component.update(); component.find(deleteButtonIdentifier).first().simulate('click'); - expect(component.find(confirmModalIndentifier).exists()).toBe(true); + expect(component.find(confirmModalIdentifier).exists()).toBe(true); await act(async () => { // @ts-ignore - await component.find(confirmModalIndentifier).props().onConfirm(); + await component.find(confirmModalIdentifier).props().onConfirm(); }); component.update(); expect(utils.deleteMultipleDataSources).toHaveBeenCalled(); // @ts-ignore - expect(component.find(confirmModalIndentifier).exists()).toBe(false); + expect(component.find(confirmModalIdentifier).exists()).toBe(false); }); }); }); diff --git a/src/plugins/data_source_management/public/components/data_source_table/data_source_table.tsx b/src/plugins/data_source_management/public/components/data_source_table/data_source_table.tsx index f4f537436e05..15faf57f57a2 100644 --- a/src/plugins/data_source_management/public/components/data_source_table/data_source_table.tsx +++ b/src/plugins/data_source_management/public/components/data_source_table/data_source_table.tsx @@ -20,6 +20,7 @@ import React, { useState } from 'react'; import { RouteComponentProps, withRouter } from 'react-router-dom'; import { useEffectOnce } from 'react-use'; import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; import { getListBreadcrumbs } from '../breadcrumbs'; import { reactRouterNavigate, @@ -29,19 +30,6 @@ import { DataSourceManagementContext, DataSourceTableItem, ToastMessageItem } fr import { CreateButton } from '../create_button'; import { deleteMultipleDataSources, getDataSources } from '../utils'; import { LoadingMask } from '../loading_mask'; -import { - CANCEL_TEXT, - DELETE_TEXT, - DS_LISTING_ARIA_REGION, - DS_LISTING_DATA_SOURCE_DELETE_ACTION, - DS_LISTING_DATA_SOURCE_DELETE_IMPACT, - DS_LISTING_DATA_SOURCE_DELETE_WARNING, - DS_LISTING_DATA_SOURCE_MULTI_DELETE_TITLE, - DS_LISTING_DESCRIPTION, - DS_LISTING_NO_DATA, - DS_LISTING_PAGE_TITLE, - DS_LISTING_TITLE, -} from '../text_content/text_content'; /* Table config */ const pagination = { @@ -77,7 +65,11 @@ export const DataSourceTable = ({ history }: RouteComponentProps) => { setBreadcrumbs(getListBreadcrumbs()); /* Browser - Page Title */ - chrome.docTitle.change(DS_LISTING_PAGE_TITLE); + chrome.docTitle.change( + i18n.translate('dataSourcesManagement.dataSourcesTable.dataSourcesTitle', { + defaultMessage: 'Data Sources', + }) + ); /* fetch data sources*/ fetchDataSources(); @@ -176,7 +168,9 @@ export const DataSourceTable = ({ history }: RouteComponentProps) => { const tableRenderDeleteModal = () => { return confirmDeleteVisible ? ( { setConfirmDeleteVisible(false); }} @@ -184,13 +178,38 @@ export const DataSourceTable = ({ history }: RouteComponentProps) => { setConfirmDeleteVisible(false); onClickDelete(); }} - cancelButtonText={CANCEL_TEXT} - confirmButtonText={DELETE_TEXT} + cancelButtonText={i18n.translate('dataSourcesManagement.dataSourcesTable.cancel', { + defaultMessage: 'Cancel', + })} + confirmButtonText={i18n.translate('dataSourcesManagement.dataSourcesTable.delete', { + defaultMessage: 'Delete', + })} defaultFocusedButton="confirm" > -

{DS_LISTING_DATA_SOURCE_DELETE_ACTION}

-

{DS_LISTING_DATA_SOURCE_DELETE_IMPACT}

-

{DS_LISTING_DATA_SOURCE_DELETE_WARNING}

+

+ { + + } +

+

+ { + + } +

+

+ { + + } +

) : null; }; @@ -247,11 +266,25 @@ export const DataSourceTable = ({ history }: RouteComponentProps) => { -

{DS_LISTING_TITLE}

+

+ { + + } +

-

{DS_LISTING_DESCRIPTION}

+

+ { + + } +

{createButton} @@ -284,8 +317,20 @@ export const DataSourceTable = ({ history }: RouteComponentProps) => { return ( <> - - {DS_LISTING_NO_DATA} + + + { + + } + {createButton} @@ -300,7 +345,9 @@ export const DataSourceTable = ({ history }: RouteComponentProps) => { {/* Header */} {renderHeader()} diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx index 424d4cb9f5a8..61a7f3ba1f9b 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx @@ -21,6 +21,9 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; +import { Header } from '../header'; import { AuthType, credentialSourceOptions, @@ -28,7 +31,6 @@ import { DataSourceManagementContextValue, UsernamePasswordTypedContent, } from '../../../../types'; -import { Header } from '../header'; import { context as contextType } from '../../../../../../opensearch_dashboards_react/public'; import { CreateEditDataSourceValidation, @@ -37,28 +39,6 @@ import { performDataSourceFormValidation, } from '../../../validation'; import { UpdatePasswordModal } from '../update_password_modal'; -import { - AUTHENTICATION_METHOD, - AUTHENTICATION_TITLE, - CANCEL_CHANGES, - CONNECTION_DETAILS_TITLE, - DATA_SOURCE_DESCRIPTION_PLACEHOLDER, - DATA_SOURCE_PASSWORD_PLACEHOLDER, - USERNAME_PLACEHOLDER, - CREDENTIAL, - DESCRIPTION, - ENDPOINT_DESCRIPTION, - ENDPOINT_TITLE, - ENDPOINT_URL, - OBJECT_DETAILS_DESCRIPTION, - OBJECT_DETAILS_TITLE, - OPTIONAL, - PASSWORD, - SAVE_CHANGES, - TITLE, - UPDATE_STORED_PASSWORD, - USERNAME, -} from '../../../text_content'; export interface EditDataSourceProps { existingDataSource: DataSourceAttributes; @@ -295,7 +275,14 @@ export class EditDataSourceForm extends React.Component { return ( <> - {UPDATE_STORED_PASSWORD} + + { + + } + {this.state.showUpdatePasswordModal ? ( { + renderFieldLabelAsOptional = (i18nId: string, defaultMessage: string) => { return ( <> - {label} - {OPTIONAL} + {}{' '} + + -{' '} + { + + } + ); }; @@ -332,36 +328,75 @@ export class EditDataSourceForm extends React.Component -

{CONNECTION_DETAILS_TITLE}

+

+ { + + } +

{OBJECT_DETAILS_TITLE}} - description={

{OBJECT_DETAILS_DESCRIPTION}

} + title={ +

+ { + + } +

+ } + description={ +

+ { + + } +

+ } > {/* Title */} {/* Description */} - + @@ -375,17 +410,46 @@ export class EditDataSourceForm extends React.Component -

{ENDPOINT_TITLE}

+

+ { + + } +

{ENDPOINT_URL}} - description={

{ENDPOINT_DESCRIPTION}

} + title={ +

+ { + + } +

+ } + description={ +

+ { + + } +

+ } > {/* Endpoint */} - + -

{AUTHENTICATION_TITLE}

+

+ { + + } +

- {AUTHENTICATION_METHOD}}> + + { + + } + + } + > {this.renderCredentialsSection()}
@@ -420,7 +502,11 @@ export class EditDataSourceForm extends React.Component {/* Auth type select */} - + {/* Username */} - {CANCEL_CHANGES} + { + + } @@ -548,7 +653,12 @@ export class EditDataSourceForm extends React.Component - {SAVE_CHANGES} + { + + } diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx index 974e29ff0635..2dda7b4ccf75 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx @@ -14,17 +14,10 @@ import { EuiButtonIcon, EuiConfirmModal, } from '@elastic/eui'; - +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; import { useOpenSearchDashboards } from '../../../../../../opensearch_dashboards_react/public'; import { DataSourceManagementContext } from '../../../../types'; -import { - CANCEL_TEXT, - DELETE_TEXT, - DS_LISTING_DATA_SOURCE_DELETE_IMPACT, - DS_LISTING_DATA_SOURCE_DELETE_WARNING, - DELETE_THIS_DATA_SOURCE, - DS_UPDATE_DATA_SOURCE_DELETE_TITLE, -} from '../../../text_content'; export const Header = ({ showDeleteIcon, @@ -46,7 +39,11 @@ export const Header = ({ const renderDeleteButton = () => { return ( <> - + { @@ -55,13 +52,20 @@ export const Header = ({ iconType="trash" iconSize="m" size="m" - aria-label={DELETE_THIS_DATA_SOURCE} + aria-label={i18n.translate( + 'dataSourcesManagement.editDataSource.deleteThisDataSource', + { + defaultMessage: 'Delete this Data Source', + } + )} /> {isDeleteModalVisible ? ( { setIsDeleteModalVisible(false); }} @@ -69,12 +73,30 @@ export const Header = ({ setIsDeleteModalVisible(false); onClickDeleteIcon(); }} - cancelButtonText={CANCEL_TEXT} - confirmButtonText={DELETE_TEXT} + cancelButtonText={i18n.translate('dataSourcesManagement.editDataSource.cancel', { + defaultMessage: 'Cancel', + })} + confirmButtonText={i18n.translate('dataSourcesManagement.editDataSource.delete', { + defaultMessage: 'Delete', + })} defaultFocusedButton="confirm" > -

{DS_LISTING_DATA_SOURCE_DELETE_IMPACT}

-

{DS_LISTING_DATA_SOURCE_DELETE_WARNING}

+

+ { + + } +

+

+ { + + } +

) : null} diff --git a/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx index 5e7307abc7db..aad6b8fd647c 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/components/update_password_modal/update_password_modal.tsx @@ -18,15 +18,8 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; -import { - CANCEL_TEXT, - CONFIRM_NEW_PASSWORD_TEXT, - NEW_PASSWORD_TEXT, - PASSWORD_NO_MATCH, - UPDATE_STORED_PASSWORD, - UPDATE_STORED_PASSWORD_DESCRIPTION, - USERNAME, -} from '../../../text_content'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; export interface UpdatePasswordModalProps { username: string; @@ -64,7 +57,11 @@ export const UpdatePasswordModal = ({ if (!confirmNewPassword) { invalidReason.push(''); } else if (confirmNewPassword !== newPassword) { - invalidReason.push(PASSWORD_NO_MATCH); + invalidReason.push( + i18n.translate('dataSourcesManagement.editDataSource.passwordNoMatch', { + defaultMessage: 'Passwords do not match', + }) + ); } setIsConfirmNewPasswordValid(invalidReason); }; @@ -74,28 +71,54 @@ export const UpdatePasswordModal = ({ -

{UPDATE_STORED_PASSWORD}

+

+ { + + } +

- {UPDATE_STORED_PASSWORD_DESCRIPTION} + { + + } {/* Username */} - + {username} {/* updated Password */} - + {/* Password */} - {CANCEL_TEXT} + + { + + } + - {UPDATE_STORED_PASSWORD} + {i18n.translate('dataSourcesManagement.editDataSource.updateStoredPassword', { + defaultMessage: 'Update stored password', + })}
diff --git a/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx b/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx index e502adc5d5ca..6c9c39939c51 100644 --- a/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx +++ b/src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx @@ -8,6 +8,7 @@ import React, { useState } from 'react'; import { useEffectOnce } from 'react-use'; import { EuiSpacer } from '@elastic/eui'; import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; import { DataSourceManagementContext, DataSourceTableItem, ToastMessageItem } from '../../types'; import { @@ -20,7 +21,6 @@ import { getEditBreadcrumbs } from '../breadcrumbs'; import { EditDataSourceForm } from './components/edit_form/edit_data_source_form'; import { LoadingMask } from '../loading_mask'; import { AuthType, DataSourceAttributes } from '../../types'; -import { DATA_SOURCE_NOT_FOUND } from '../text_content'; const defaultDataSource: DataSourceAttributes = { title: '', @@ -131,7 +131,16 @@ const EditDataSource: React.FunctionComponent{DATA_SOURCE_NOT_FOUND}; + return ( +

+ { + + } +

+ ); } return ( diff --git a/src/plugins/data_source_management/public/components/text_content/index.ts b/src/plugins/data_source_management/public/components/text_content/index.ts deleted file mode 100644 index 6caa2514600b..000000000000 --- a/src/plugins/data_source_management/public/components/text_content/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -export * from './text_content'; diff --git a/src/plugins/data_source_management/public/components/text_content/text_content.ts b/src/plugins/data_source_management/public/components/text_content/text_content.ts deleted file mode 100644 index 5a26668ff2c6..000000000000 --- a/src/plugins/data_source_management/public/components/text_content/text_content.ts +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { i18n } from '@osd/i18n'; - -/* Generic */ -export const CANCEL_TEXT = i18n.translate('cancel', { - defaultMessage: 'Cancel', -}); - -export const DELETE_TEXT = i18n.translate('delete', { - defaultMessage: 'Delete', -}); - -export const TITLE = i18n.translate('title', { - defaultMessage: 'Title', -}); - -export const DESCRIPTION = i18n.translate('description', { - defaultMessage: 'Description', -}); - -export const OPTIONAL = i18n.translate('optional', { - defaultMessage: 'optional', -}); - -export const USERNAME = i18n.translate('username', { - defaultMessage: 'Username', -}); - -export const PASSWORD = i18n.translate('password', { - defaultMessage: 'Password', -}); - -/* Datasource listing page */ -export const DS_LISTING_ARIA_REGION = i18n.translate( - 'dataSourcesManagement.createDataSourcesLiveRegionAriaLabel', - { - defaultMessage: 'Data Sources', - } -); -export const DS_LISTING_TITLE = i18n.translate('dataSourcesManagement.dataSourcesTable.title', { - defaultMessage: 'Data Sources', -}); - -export const DS_LISTING_DESCRIPTION = i18n.translate( - 'dataSourcesManagement.dataSourcesTable.description', - { - defaultMessage: - 'Create and manage data source connections to help you retrieve data from multiple OpenSearch compatible sources.', - } -); - -export const DS_LISTING_PAGE_TITLE = i18n.translate( - 'dataSourcesManagement.dataSourcesTable.dataSourcesTitle', - { - defaultMessage: 'Data Sources', - } -); - -export const DS_LISTING_NO_DATA = i18n.translate('dataSourcesManagement.dataSourcesTable.noData', { - defaultMessage: 'No Data Source Connections have been created yet.', -}); - -export const DS_LISTING_DATA_SOURCE_MULTI_DELETE_TITLE = i18n.translate( - 'dataSourcesManagement.dataSourcesTable.multiDeleteTitle', - { - defaultMessage: 'Delete data source connection(s)', - } -); - -export const DS_UPDATE_DATA_SOURCE_DELETE_TITLE = i18n.translate( - 'dataSourcesManagement.dataSourcesUpdate.deleteTitle', - { - defaultMessage: 'Delete data source connection', - } -); - -export const DS_LISTING_DATA_SOURCE_DELETE_ACTION = i18n.translate( - 'dataSourcesManagement.dataSourcesTable.deleteDescription', - { - defaultMessage: 'This action will delete the selected data source connections', - } -); - -export const DS_LISTING_DATA_SOURCE_DELETE_IMPACT = i18n.translate( - 'dataSourcesManagement.dataSourcesTable.deleteConfirmation', - { - defaultMessage: - 'Any objects created using data from these sources, including Index Patterns, Visualizations, and Observability Panels, will be impacted.', - } -); - -export const DS_LISTING_DATA_SOURCE_DELETE_WARNING = i18n.translate( - 'dataSourcesManagement.dataSourcesTable.deleteWarning', - { - defaultMessage: 'This action cannot be undone.', - } -); - -/* CREATE DATA SOURCE */ -export const CREATE_DATA_SOURCE_BUTTON_TEXT = i18n.translate( - 'dataSourcesManagement.dataSourceListing.createButton', - { - defaultMessage: 'Create data source connection', - } -); -export const CREATE_DATA_SOURCE_HEADER = i18n.translate( - 'dataSourcesManagement.createDataSourceHeader', - { - defaultMessage: 'Create data source connection', - } -); -export const DATA_SOURCE_DESCRIPTION_PLACEHOLDER = i18n.translate( - 'dataSourcesManagement.createDataSource.descriptionPlaceholder', - { - defaultMessage: 'Description of the data source', - } -); -export const ENDPOINT_URL = i18n.translate('dataSourcesManagement.createDataSource.endpointURL', { - defaultMessage: 'Endpoint URL', -}); -export const ENDPOINT_PLACEHOLDER = i18n.translate( - 'dataSourcesManagement.createDataSource.endpointPlaceholder', - { - defaultMessage: 'Sample URL: https://connectionurl.com', - } -); -export const USERNAME_PLACEHOLDER = i18n.translate( - 'dataSourcesManagement.createDataSource.usernamePlaceholder', - { - defaultMessage: 'Username to connect to data source', - } -); -export const DATA_SOURCE_PASSWORD_PLACEHOLDER = i18n.translate( - 'dataSourcesManagement.createDataSource.passwordPlaceholder', - { - defaultMessage: 'Password to connect to data source', - } -); -export const CREDENTIAL_SOURCE = i18n.translate( - 'dataSourcesManagement.createDataSource.credentialSource', - { - defaultMessage: 'Credential Source', - } -); -export const AUTHENTICATION_METHOD_DESCRIPTION = i18n.translate( - 'dataSourcesManagement.createDataSource.authenicationMethodDescription', - { - defaultMessage: - 'Provide authentication details require to gain access to the endpoint. If no authentication is required, choose ', - } -); -export const NO_AUTHENTICATION = i18n.translate( - 'dataSourcesManagement.createDataSource.noAuthentication', - { - defaultMessage: 'No authentication', - } -); - -/* Edit data source */ -export const DATA_SOURCE_NOT_FOUND = i18n.translate( - 'dataSourcesManagement.editDataSource.dataSourceNotFound', - { - defaultMessage: 'Data Source not found!', - } -); -export const DELETE_THIS_DATA_SOURCE = i18n.translate( - 'dataSourcesManagement.editDataSource.deleteThisDataSource', - { - defaultMessage: 'Delete this Data Source', - } -); -export const NEW_PASSWORD_TEXT = i18n.translate( - 'dataSourcesManagement.editDataSource.newPassword', - { - defaultMessage: 'Updated password', - } -); -export const CONFIRM_NEW_PASSWORD_TEXT = i18n.translate( - 'dataSourcesManagement.editDataSource.confirmNewPassword', - { - defaultMessage: 'Confirm Updated password', - } -); -export const PASSWORD_NO_MATCH = i18n.translate( - 'dataSourcesManagement.editDataSource.passwordNoMatch', - { - defaultMessage: 'Passwords do not match', - } -); -export const UPDATE_STORED_PASSWORD = i18n.translate( - 'dataSourcesManagement.editDataSource.updateStoredPassword', - { - defaultMessage: 'Update stored password', - } -); -export const UPDATE_STORED_PASSWORD_DESCRIPTION = i18n.translate( - 'dataSourcesManagement.editDataSource.updateStoredPasswordDescription', - { - defaultMessage: - 'Update credential password to reflect accurate password to gain access to the endpoint.', - } -); -export const CONNECTION_DETAILS_TITLE = i18n.translate( - 'dataSourcesManagement.editDataSource.connectionDetailsText', - { - defaultMessage: 'Connection Details', - } -); -export const OBJECT_DETAILS_TITLE = i18n.translate( - 'dataSourcesManagement.editDataSource.objectDetailsText', - { - defaultMessage: 'Object Details', - } -); -export const OBJECT_DETAILS_DESCRIPTION = i18n.translate( - 'dataSourcesManagement.editDataSource.objectDetailsDescription', - { - defaultMessage: - 'This connection information is used for reference in tables and when adding to a data source connection', - } -); -export const CREDENTIAL = i18n.translate('dataSourcesManagement.editDataSource.credential', { - defaultMessage: 'Credential', -}); -export const AUTHENTICATION_TITLE = i18n.translate( - 'dataSourcesManagement.editDataSource.authenticationTitle', - { - defaultMessage: 'Authentication', - } -); -export const AUTHENTICATION_METHOD = i18n.translate( - 'dataSourcesManagement.editDataSource.authenticationMethod', - { - defaultMessage: 'Authentication Method', - } -); -export const ENDPOINT_TITLE = i18n.translate('dataSourcesManagement.editDataSource.endpointTitle', { - defaultMessage: 'Endpoint', -}); -export const ENDPOINT_DESCRIPTION = i18n.translate( - 'dataSourcesManagement.editDataSource.endpointDescription', - { - defaultMessage: - 'This connection information is used for reference in tables and when adding to a data source connection', - } -); - -export const CANCEL_CHANGES = i18n.translate( - 'dataSourcesManagement.editDataSource.cancelButtonLabel', - { - defaultMessage: 'Cancel changes', - } -); -export const SAVE_CHANGES = i18n.translate('dataSourcesManagement.editDataSource.saveButtonLabel', { - defaultMessage: 'Save changes', -}); - -/* Create/Edit validation */ -export const DATA_SOURCE_VALIDATION_TITLE_EXISTS = i18n.translate( - 'dataSourcesManagement.validation.titleExists', - { - defaultMessage: 'This title is already in use', - } -); - -/* Experimental call out text */ -export const EXPERIMENTAL_FEATURE = i18n.translate('experimentalFeature', { - defaultMessage: 'Experimental Feature', -}); -export const EXPERIMENTAL_FEATURE_CALL_OUT_DESCRIPTION = i18n.translate( - 'dataSourcesManagement.experimentalFeatureCallout.description', - { - defaultMessage: - 'The feature is experimental and should not be used in a production environment. Any index patterns, visualization, and observability panels will be impacted if the feature is deactivated. For more information see ', - } -); -export const DATA_SOURCE_DOCUMENTATION_TEXT = i18n.translate( - 'dataSourcesManagement.experimentalFeatureCallout.documentationText', - { - defaultMessage: 'Data Source Documentation', - } -); -export const DATA_SOURCE_LEAVE_FEEDBACK_TEXT = i18n.translate( - 'dataSourcesManagement.experimentalFeatureCallout.feedbackText', - { - defaultMessage: 'To leave feedback, visit ', - } -); -export const DATA_SOURCE_OPEN_FORUM_TEXT = i18n.translate( - 'dataSourcesManagement.experimentalFeatureCallout.openForumText', - { - defaultMessage: 'OpenSearch Forum', - } -); diff --git a/src/plugins/data_source_management/public/components/validation/datasource_form_validation.ts b/src/plugins/data_source_management/public/components/validation/datasource_form_validation.ts index 4e5a465d57fb..0e861f1184f3 100644 --- a/src/plugins/data_source_management/public/components/validation/datasource_form_validation.ts +++ b/src/plugins/data_source_management/public/components/validation/datasource_form_validation.ts @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { i18n } from '@osd/i18n'; import { isValidUrl } from '../utils'; -import { DATA_SOURCE_VALIDATION_TITLE_EXISTS } from '../text_content'; import { CreateDataSourceState } from '../create_data_source_wizard/components/create_form/create_data_source_form'; import { EditDataSourceState } from '../edit_data_source/components/edit_form/edit_data_source_form'; import { AuthType } from '../../types'; @@ -46,7 +46,9 @@ export const isTitleValid = ( ) { /* title already exists */ isValid.valid = false; - isValid.error = DATA_SOURCE_VALIDATION_TITLE_EXISTS; + isValid.error = i18n.translate('dataSourcesManagement.validation.titleExists', { + defaultMessage: 'This title is already in use', + }); } return isValid; }; diff --git a/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/__snapshots__/experimental_callout.test.tsx.snap b/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/__snapshots__/experimental_callout.test.tsx.snap deleted file mode 100644 index f3c2e06db210..000000000000 --- a/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/__snapshots__/experimental_callout.test.tsx.snap +++ /dev/null @@ -1,133 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Datasource experimental callout component should render normally 1`] = ` - - -
-
- - - Experimental Feature - -
- -
- -
-

- The feature is experimental and should not be used in a production environment. Any index patterns, visualization, and observability panels will be impacted if the feature is deactivated. For more information see - - - Data Source Documentation - - - - - - - (opens in a new tab or window) - - - - - - - To leave feedback, visit - - - -

-
-
-
-
-
-
- -
- - -`; diff --git a/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.test.tsx b/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.test.tsx deleted file mode 100644 index cd61e0ea2056..000000000000 --- a/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { mount } from 'enzyme'; -import { ExperimentalCallout } from './experimental_callout'; -import { DocLinksStart } from 'opensearch-dashboards/public'; -import { docLinks } from '../../../mocks'; - -const titleIdentifier = '.euiCallOutHeader__title'; -const descriptionIdentifier = '[data-test-subj="data-source-experimental-call"]'; -const expectedTitleText = 'Experimental Feature'; -const expectedDescriptionText = - 'Experimental FeatureThe feature is experimental and should not be used in a production environment. Any index patterns, visualization, and observability panels will be impacted if the feature is deactivated. For more information see Data Source Documentation(opens in a new tab or window) To leave feedback, visit OpenSearch Forum'; - -describe('Datasource experimental callout component', () => { - test('should render normally', () => { - const mockedDocLinks = docLinks as DocLinksStart; - const component = mount(); - const titleText = component.find(titleIdentifier).text(); - const descriptionText = component.find(descriptionIdentifier).last().text(); - - expect(titleText).toBe(expectedTitleText); - expect(descriptionText).toBe(expectedDescriptionText); - expect(component).toMatchSnapshot(); - }); -}); diff --git a/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.tsx b/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.tsx index 83e3721e19e8..611e410e373a 100644 --- a/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.tsx +++ b/src/plugins/data_source_management/public/management_app/compoenent/experimental_callout/experimental_callout.tsx @@ -6,30 +6,47 @@ import React from 'react'; import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; import { DocLinksStart } from 'opensearch-dashboards/public'; -import { - EXPERIMENTAL_FEATURE, - EXPERIMENTAL_FEATURE_CALL_OUT_DESCRIPTION, - DATA_SOURCE_LEAVE_FEEDBACK_TEXT, - DATA_SOURCE_DOCUMENTATION_TEXT, - DATA_SOURCE_OPEN_FORUM_TEXT, -} from '../../../components/text_content'; +import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; export const ExperimentalCallout = ({ docLinks }: { docLinks: DocLinksStart }) => { return ( <>

- {EXPERIMENTAL_FEATURE_CALL_OUT_DESCRIPTION} + { + + } - {DATA_SOURCE_DOCUMENTATION_TEXT} - {' '} - {DATA_SOURCE_LEAVE_FEEDBACK_TEXT} + { + + } + + { + + } - {DATA_SOURCE_OPEN_FORUM_TEXT} + { + + }

diff --git a/src/plugins/index_pattern_management/public/components/experimental_callout/__snapshots__/experimental_callout.test.tsx.snap b/src/plugins/index_pattern_management/public/components/experimental_callout/__snapshots__/experimental_callout.test.tsx.snap deleted file mode 100644 index 16d951e8ebc7..000000000000 --- a/src/plugins/index_pattern_management/public/components/experimental_callout/__snapshots__/experimental_callout.test.tsx.snap +++ /dev/null @@ -1,87 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Index pattern experimental callout component should render normally 1`] = ` - - -
-
- - - Experimental feature active - -
- -
- -
- -
-

- The experimental feature - - Data Source Connection - - is active. To create an index pattern without using data from an external source, use - - default - - . Any index pattern created using an external data source will result in an error if the experimental feature is deactivated. -

-
-
-
-
-
-
-
-
- -
- - -`; diff --git a/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.test.tsx b/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.test.tsx deleted file mode 100644 index a00fb635bd02..000000000000 --- a/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.test.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { mount } from 'enzyme'; -import { ExperimentalCallout } from './experimental_callout'; - -const titleIdentifier = '.euiCallOutHeader__title'; -const descriptionIdentifier = '[data-test-subj="index-pattern-experimental-callout-text"]'; -const expectedTitleText = 'Experimental feature active'; -const expectedDescriptionText = - 'The experimental feature Data Source Connection is active. To create an index pattern without using data from an external source, use default. Any index pattern created using an external data source will result in an error if the experimental feature is deactivated.'; - -describe('Index pattern experimental callout component', () => { - test('should render normally', () => { - const component = mount(); - const titleText = component.find(titleIdentifier).text(); - const descriptionText = component.find(descriptionIdentifier).last().text(); - - expect(titleText).toBe(expectedTitleText); - expect(descriptionText).toBe(expectedDescriptionText); - expect(component).toMatchSnapshot(); - }); -}); diff --git a/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.tsx b/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.tsx index 96859204d637..879ee1d98796 100644 --- a/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.tsx +++ b/src/plugins/index_pattern_management/public/components/experimental_callout/experimental_callout.tsx @@ -5,24 +5,54 @@ import React from 'react'; import { i18n } from '@osd/i18n'; +import { FormattedMessage } from '@osd/i18n/react'; import { EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; export const ExperimentalCallout = () => { return ( <>

- {DESCRIPTION_FIRST_PART} - {DATASOURCE_CONNECTION} - {DESCRIPTION_SECOND_PART} - {DEFAULT} - {DESCRIPTION_THIRD_PART} + + + + ), + }} + /> + + + + ), + }} + /> +

@@ -30,37 +60,3 @@ export const ExperimentalCallout = () => { ); }; - -const TITLE = i18n.translate('indexPatternManagement.experimentalFeatureCallout.title', { - defaultMessage: 'Experimental feature active', -}); - -const DESCRIPTION_FIRST_PART = i18n.translate( - 'indexPatternManagement.experimentalFeatureCallout.descriptionPartOne', - { - defaultMessage: 'The experimental feature ', - } -); -const DATASOURCE_CONNECTION = i18n.translate( - 'indexPatternManagement.experimentalFeatureCallout.datasourceConnection', - { - defaultMessage: 'Data Source Connection ', - } -); -const DESCRIPTION_SECOND_PART = i18n.translate( - 'indexPatternManagement.experimentalFeatureCallout.descriptionPartTwo', - { - defaultMessage: - 'is active. To create an index pattern without using data from an external source, use ', - } -); -const DEFAULT = i18n.translate('indexPatternManagement.experimentalFeatureCallout.default', { - defaultMessage: 'default', -}); -const DESCRIPTION_THIRD_PART = i18n.translate( - 'indexPatternManagement.experimentalFeatureCallout.descriptionPartThree', - { - defaultMessage: - '. Any index pattern created using an external data source will result in an error if the experimental feature is deactivated.', - } -);