Skip to content

Commit c9bb5a8

Browse files
Add set default datasource (#6186)
* Add set default datasource Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * Fix typo Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * change on this.props.isDefault Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * add unit test Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * set data_source to false Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * add more unit test Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * fix lint error Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * edit one more unit test Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> * Fix another typo Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> --------- Signed-off-by: Yuanqi(Ella) Zhu <[email protected]> Co-authored-by: ZilongX <[email protected]> (cherry picked from commit d2347ca) Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> # Conflicts: # CHANGELOG.md
1 parent 52fca45 commit c9bb5a8

File tree

6 files changed

+153
-0
lines changed

6 files changed

+153
-0
lines changed

src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.test.tsx

+14
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,10 @@ describe('Datasource Management: Edit Datasource Form', () => {
7676
<EditDataSourceForm
7777
existingDataSource={mockDataSourceAttributesWithAuth}
7878
existingDatasourceNamesList={existingDatasourceNamesList}
79+
isDefault={false}
7980
onDeleteDataSource={mockFn}
8081
handleSubmit={mockFn}
82+
onSetDefaultDataSource={mockFn}
8183
handleTestConnection={mockFn}
8284
displayToastMessage={mockFn}
8385
/>
@@ -245,7 +247,9 @@ describe('Datasource Management: Edit Datasource Form', () => {
245247
<EditDataSourceForm
246248
existingDataSource={mockDataSourceAttributesWithNoAuth}
247249
existingDatasourceNamesList={existingDatasourceNamesList}
250+
isDefault={false}
248251
onDeleteDataSource={mockFn}
252+
onSetDefaultDataSource={mockFn}
249253
handleSubmit={mockFn}
250254
handleTestConnection={mockFn}
251255
displayToastMessage={mockFn}
@@ -301,6 +305,12 @@ describe('Datasource Management: Edit Datasource Form', () => {
301305
expect(mockFn).toHaveBeenCalled();
302306
});
303307

308+
test('should set as the default datasource from header', () => {
309+
// @ts-ignore
310+
component.find('Header').prop('onClickSetDefault')();
311+
expect(mockFn).toHaveBeenCalled();
312+
});
313+
304314
/* Save Changes */
305315
test('should update the form with NoAuth on click save changes', async () => {
306316
await new Promise((resolve) =>
@@ -383,8 +393,10 @@ describe('With Registered Authentication', () => {
383393
<EditDataSourceForm
384394
existingDataSource={mockDataSourceAttributesWithNoAuth}
385395
existingDatasourceNamesList={existingDatasourceNamesList}
396+
isDefault={false}
386397
onDeleteDataSource={jest.fn()}
387398
handleSubmit={jest.fn()}
399+
onSetDefaultDataSource={jest.fn()}
388400
handleTestConnection={jest.fn()}
389401
displayToastMessage={jest.fn()}
390402
/>
@@ -422,8 +434,10 @@ describe('With Registered Authentication', () => {
422434
<EditDataSourceForm
423435
existingDataSource={mockDataSourceAttributesWithRegisteredAuth}
424436
existingDatasourceNamesList={existingDatasourceNamesList}
437+
isDefault={false}
425438
onDeleteDataSource={jest.fn()}
426439
handleSubmit={mockedSubmitHandler}
440+
onSetDefaultDataSource={jest.fn()}
427441
handleTestConnection={jest.fn()}
428442
displayToastMessage={jest.fn()}
429443
/>

src/plugins/data_source_management/public/components/edit_data_source/components/edit_form/edit_data_source_form.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ import { extractRegisteredAuthTypeCredentials, getDefaultAuthMethod } from '../.
5050
export interface EditDataSourceProps {
5151
existingDataSource: DataSourceAttributes;
5252
existingDatasourceNamesList: string[];
53+
isDefault: boolean;
5354
handleSubmit: (formValues: DataSourceAttributes) => Promise<void>;
5455
handleTestConnection: (formValues: DataSourceAttributes) => Promise<void>;
5556
onDeleteDataSource?: () => Promise<void>;
57+
onSetDefaultDataSource: () => Promise<void>;
5658
displayToastMessage: (info: ToastMessageItem) => void;
5759
}
5860
export interface EditDataSourceState {
@@ -400,6 +402,12 @@ export class EditDataSourceForm extends React.Component<EditDataSourceProps, Edi
400402
}
401403
};
402404

405+
setDefaultDataSource = async () => {
406+
if (this.props.onSetDefaultDataSource) {
407+
await this.props.onSetDefaultDataSource();
408+
}
409+
};
410+
403411
onClickTestConnection = async () => {
404412
this.setState({ isLoading: true });
405413
const isNewCredential = !!(this.state.auth.type !== this.props.existingDataSource.auth.type);
@@ -634,6 +642,8 @@ export class EditDataSourceForm extends React.Component<EditDataSourceProps, Edi
634642
onClickDeleteIcon={this.onClickDeleteDataSource}
635643
dataSourceName={this.props.existingDataSource.title}
636644
onClickTestConnection={this.onClickTestConnection}
645+
onClickSetDefault={this.setDefaultDataSource}
646+
isDefault={this.props.isDefault}
637647
/>
638648
);
639649
};

src/plugins/data_source_management/public/components/edit_data_source/components/header/header.test.tsx

+77
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { act } from 'react-dom/test-utils';
1414
const headerTitleIdentifier = '[data-test-subj="editDataSourceTitle"]';
1515
const deleteIconIdentifier = '[data-test-subj="editDatasourceDeleteIcon"]';
1616
const confirmModalIdentifier = '[data-test-subj="editDatasourceDeleteConfirmModal"]';
17+
const setDefaultButtonIdentifier = '[data-test-subj="editSetDefaultDataSource"]';
1718

1819
describe('Datasource Management: Edit Datasource Header', () => {
1920
const mockedContext = mockManagementPlugin.createDataSourceManagementContext();
@@ -31,6 +32,8 @@ describe('Datasource Management: Edit Datasource Header', () => {
3132
onClickDeleteIcon={mockFn}
3233
onClickTestConnection={mockFn}
3334
dataSourceName={dataSourceName}
35+
onClickSetDefault={mockFn}
36+
isDefault={false}
3437
/>
3538
),
3639
{
@@ -82,6 +85,8 @@ describe('Datasource Management: Edit Datasource Header', () => {
8285
onClickDeleteIcon={mockFn}
8386
onClickTestConnection={mockFn}
8487
dataSourceName={dataSourceName}
88+
onClickSetDefault={mockFn}
89+
isDefault={false}
8590
/>
8691
),
8792
{
@@ -97,4 +102,76 @@ describe('Datasource Management: Edit Datasource Header', () => {
97102
expect(component.find(deleteIconIdentifier).exists()).toBe(false);
98103
});
99104
});
105+
describe('should render default icon as "Set as default" when isDefaultDataSourceState is false', () => {
106+
const onClickSetDefault = jest.fn();
107+
const isDefaultDataSourceState = false;
108+
beforeEach(() => {
109+
component = mount(
110+
wrapWithIntl(
111+
<Header
112+
isFormValid={true}
113+
showDeleteIcon={true}
114+
onClickDeleteIcon={mockFn}
115+
onClickTestConnection={mockFn}
116+
dataSourceName={dataSourceName}
117+
onClickSetDefault={onClickSetDefault}
118+
isDefault={isDefaultDataSourceState}
119+
/>
120+
),
121+
{
122+
wrappingComponent: OpenSearchDashboardsContextProvider,
123+
wrappingComponentProps: {
124+
services: mockedContext,
125+
},
126+
}
127+
);
128+
});
129+
130+
test('should render normally', () => {
131+
expect(component.find(setDefaultButtonIdentifier).exists()).toBe(true);
132+
});
133+
test('default button should show as "Set as default" and should be clickable', () => {
134+
expect(component.find(setDefaultButtonIdentifier).first().text()).toBe('Set as default');
135+
expect(component.find(setDefaultButtonIdentifier).first().prop('disabled')).toBe(false);
136+
expect(component.find(setDefaultButtonIdentifier).first().prop('iconType')).toBe('starEmpty');
137+
component.find(setDefaultButtonIdentifier).first().simulate('click');
138+
expect(onClickSetDefault).toHaveBeenCalled();
139+
});
140+
});
141+
describe('should render default icon as "Default" when isDefaultDataSourceState is true', () => {
142+
const onClickSetDefault = jest.fn();
143+
const isDefaultDataSourceState = true;
144+
beforeEach(() => {
145+
component = mount(
146+
wrapWithIntl(
147+
<Header
148+
isFormValid={true}
149+
showDeleteIcon={true}
150+
onClickDeleteIcon={mockFn}
151+
onClickTestConnection={mockFn}
152+
dataSourceName={dataSourceName}
153+
onClickSetDefault={onClickSetDefault}
154+
isDefault={isDefaultDataSourceState}
155+
/>
156+
),
157+
{
158+
wrappingComponent: OpenSearchDashboardsContextProvider,
159+
wrappingComponentProps: {
160+
services: mockedContext,
161+
},
162+
}
163+
);
164+
});
165+
166+
test('should render normally', () => {
167+
expect(component.find(setDefaultButtonIdentifier).exists()).toBe(true);
168+
});
169+
test('default button should show as "Default" and should be disabled.', () => {
170+
expect(component.find(setDefaultButtonIdentifier).first().text()).toBe('Default');
171+
expect(component.find(setDefaultButtonIdentifier).first().prop('disabled')).toBe(true);
172+
expect(component.find(setDefaultButtonIdentifier).first().prop('iconType')).toBe(
173+
'starFilled'
174+
);
175+
});
176+
});
100177
});

src/plugins/data_source_management/public/components/edit_data_source/components/header/header.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
EuiButtonIcon,
1515
EuiConfirmModal,
1616
EuiButton,
17+
EuiButtonEmpty,
1718
} from '@elastic/eui';
1819
import { i18n } from '@osd/i18n';
1920
import { FormattedMessage } from '@osd/i18n/react';
@@ -25,22 +26,51 @@ export const Header = ({
2526
isFormValid,
2627
onClickDeleteIcon,
2728
onClickTestConnection,
29+
onClickSetDefault,
2830
dataSourceName,
31+
isDefault,
2932
}: {
3033
showDeleteIcon: boolean;
3134
isFormValid: boolean;
3235
onClickDeleteIcon: () => void;
3336
onClickTestConnection: () => void;
37+
onClickSetDefault: () => void;
3438
dataSourceName: string;
39+
isDefault: boolean;
3540
}) => {
3641
/* State Variables */
3742
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
43+
const [isDefaultDataSourceState, setIsDefaultDataSourceState] = useState(isDefault);
3844

3945
const changeTitle = useOpenSearchDashboards<DataSourceManagementContext>().services.chrome
4046
.docTitle.change;
4147

4248
changeTitle(dataSourceName);
4349

50+
const setDefaultAriaLabel = i18n.translate(
51+
'dataSourcesManagement.editDataSource.setDefaultDataSource',
52+
{
53+
defaultMessage: 'Set as a default Data Source.',
54+
}
55+
);
56+
57+
const renderDefaultIcon = () => {
58+
return (
59+
<EuiButtonEmpty
60+
onClick={() => {
61+
onClickSetDefault();
62+
setIsDefaultDataSourceState(!isDefaultDataSourceState);
63+
}}
64+
disabled={isDefaultDataSourceState}
65+
iconType={isDefaultDataSourceState ? 'starFilled' : 'starEmpty'}
66+
aria-label={setDefaultAriaLabel}
67+
data-test-subj="editSetDefaultDataSource"
68+
>
69+
{isDefaultDataSourceState ? 'Default' : 'Set as default'}
70+
</EuiButtonEmpty>
71+
);
72+
};
73+
4474
const renderDeleteButton = () => {
4575
return (
4676
<>
@@ -144,6 +174,8 @@ export const Header = ({
144174
{/* Right side buttons */}
145175
<EuiFlexItem grow={false}>
146176
<EuiFlexGroup alignItems="baseline" gutterSize="m" responsive={false}>
177+
{/* Test default button */}
178+
<EuiFlexItem grow={false}>{renderDefaultIcon()}</EuiFlexItem>
147179
{/* Test connection button */}
148180
<EuiFlexItem grow={false}>{renderTestConnectionButton()}</EuiFlexItem>
149181
{/* Delete icon button */}

src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.test.tsx

+11
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const notFoundIdentifier = '[data-test-subj="dataSourceNotFound"]';
2929

3030
describe('Datasource Management: Edit Datasource Wizard', () => {
3131
const mockedContext = mockManagementPlugin.createDataSourceManagementContext();
32+
const uiSettings = mockedContext.uiSettings;
3233
mockedContext.authenticationMethodRegistery.registerAuthenticationMethod(
3334
noAuthCredentialAuthMethod
3435
);
@@ -125,6 +126,16 @@ describe('Datasource Management: Edit Datasource Wizard', () => {
125126
component.update();
126127
expect(utils.updateDataSourceById).toHaveBeenCalled();
127128
});
129+
test('should set default data source', async () => {
130+
spyOn(uiSettings, 'set').and.returnValue({});
131+
await act(async () => {
132+
// @ts-ignore
133+
await component.find(formIdentifier).first().prop('onSetDefaultDataSource')(
134+
mockDataSourceAttributesWithAuth
135+
);
136+
});
137+
expect(uiSettings.set).toHaveBeenCalled();
138+
});
128139
test('should delete datasource successfully', async () => {
129140
spyOn(utils, 'deleteDataSourceById').and.returnValue({});
130141

src/plugins/data_source_management/public/components/edit_data_source/edit_data_source.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const EditDataSource: React.FunctionComponent<RouteComponentProps<{ id: s
3838
) => {
3939
/* Initialization */
4040
const {
41+
uiSettings,
4142
savedObjects,
4243
setBreadcrumbs,
4344
http,
@@ -83,6 +84,12 @@ export const EditDataSource: React.FunctionComponent<RouteComponentProps<{ id: s
8384
}
8485
};
8586

87+
const handleSetDefault = async () => {
88+
await uiSettings.set('defaultDataSource', dataSourceID);
89+
};
90+
91+
const isDefaultDataSource = uiSettings.get('defaultDataSource', null) === dataSourceID;
92+
8693
/* Handle submit - create data source*/
8794
const handleSubmit = async (attributes: DataSourceAttributes) => {
8895
await updateDataSourceById(savedObjects.client, dataSourceID, attributes);
@@ -128,7 +135,9 @@ export const EditDataSource: React.FunctionComponent<RouteComponentProps<{ id: s
128135
<EditDataSourceForm
129136
existingDataSource={dataSource}
130137
existingDatasourceNamesList={existingDatasourceNamesList}
138+
isDefault={isDefaultDataSource}
131139
onDeleteDataSource={handleDelete}
140+
onSetDefaultDataSource={handleSetDefault}
132141
handleSubmit={handleSubmit}
133142
displayToastMessage={handleDisplayToastMessage}
134143
handleTestConnection={handleTestConnection}

0 commit comments

Comments
 (0)