Skip to content

Commit

Permalink
[Enterprise Search] Add order for native connectors (#150463)
Browse files Browse the repository at this point in the history
## Summary

This adds a sort order to native connector configuration entries.
<img width="708" alt="Screenshot 2023-02-07 at 18 41 25"
src="https://user-images.githubusercontent.com/94373878/217323854-f8e59dd0-d135-40f4-ae86-f1414aebda58.png">

---------

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
sphilipse and kibanamachine authored Feb 9, 2023
1 parent 7981e47 commit 61bd0c8
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Host',
}
),
order: 0,
value: '',
},
user: {
Expand All @@ -28,6 +29,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Username',
}
),
order: 1,
value: '',
},
password: {
Expand All @@ -37,6 +39,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Password',
}
),
order: 2,
value: '',
},
database: {
Expand All @@ -46,6 +49,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Database',
}
),
order: 3,
value: '',
},
collection: {
Expand All @@ -55,6 +59,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Collection',
}
),
order: 4,
value: '',
},
direct_connection: {
Expand All @@ -64,6 +69,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Direct connection (true/false)',
}
),
order: 5,
value: '',
},
},
Expand All @@ -89,6 +95,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Host',
}
),
order: 0,
value: '',
},
port: {
Expand All @@ -98,6 +105,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Port',
}
),
order: 1,
value: '',
},
user: {
Expand All @@ -107,10 +115,12 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Username',
}
),
order: 2,
value: '',
},
password: {
value: '',
order: 3,
label: i18n.translate(
'xpack.enterpriseSearch.nativeConnectors.mysql.configuration.passwordLabel',
{
Expand All @@ -125,6 +135,27 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record<string, NativeConnector | unde
defaultMessage: 'Databases',
}
),
order: 4,
value: '',
},
ssl_disabled: {
label: i18n.translate(
'xpack.enterpriseSearch.nativeConnectors.mysql.configuration.sslDisabledLabel',
{
defaultMessage: 'Disable SSL (true/false)',
}
),
order: 5,
value: 'true',
},
ssl_ca: {
label: i18n.translate(
'xpack.enterpriseSearch.nativeConnectors.mysql.configuration.sslCertificateLabel',
{
defaultMessage: 'SSL certificate',
}
),
order: 6,
value: '',
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

export interface KeyValuePair {
label: string;
order?: number | null;
value: string | null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('updateConnectorConfigurationLogic', () => {
it('calls correct api', async () => {
const promise = Promise.resolve('result');
http.post.mockReturnValue(promise);
const configuration = { configurationKey: { label: 'hello', value: 'yeahhhh' } };
const configuration = { configurationKey: 'yeahhhh' };
const result = postConnectorConfiguration({
configuration,
connectorId: 'anIndexId',
Expand All @@ -31,7 +31,7 @@ describe('updateConnectorConfigurationLogic', () => {
'/internal/enterprise_search/connectors/anIndexId/configuration',
{ body: JSON.stringify(configuration) }
);
await expect(result).resolves.toEqual({ configuration, indexName: 'anIndexName' });
await expect(result).resolves.toEqual({ configuration: 'result', indexName: 'anIndexName' });
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import { i18n } from '@kbn/i18n';

import { ConnectorConfiguration } from '../../../../../common/types/connectors';
import { createApiLogic } from '../../../shared/api_logic/create_api_logic';
import { Actions, createApiLogic } from '../../../shared/api_logic/create_api_logic';
import { HttpLogic } from '../../../shared/http';

export interface PostConnectorConfigurationArgs {
configuration: ConnectorConfiguration;
configuration: Record<string, string>;
connectorId: string;
indexName: string;
}
Expand All @@ -29,10 +29,10 @@ export const postConnectorConfiguration = async ({
}: PostConnectorConfigurationArgs) => {
const route = `/internal/enterprise_search/connectors/${connectorId}/configuration`;

await HttpLogic.values.http.post<ConnectorConfiguration>(route, {
const responseConfig = await HttpLogic.values.http.post<ConnectorConfiguration>(route, {
body: JSON.stringify(configuration),
});
return { configuration, indexName };
return { configuration: responseConfig, indexName };
};

export const ConnectorConfigurationApiLogic = createApiLogic(
Expand All @@ -46,3 +46,8 @@ export const ConnectorConfigurationApiLogic = createApiLogic(
),
}
);

export type PostConnectorConfigurationActions = Actions<
PostConnectorConfigurationArgs,
PostConnectorConfigurationResponse
>;
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export const ConnectorConfigurationConfig: React.FC = ({ children }) => {
const { configView, isEditing } = useValues(ConnectorConfigurationLogic);
const { setIsEditing } = useActions(ConnectorConfigurationLogic);

const displayList = configView.map(({ label, value }) => ({
description: value ?? '--',
const displayList = configView.map(({ label, isPasswordField, value }) => ({
description: isPasswordField && !!value ? '********' : value || '--',
title: label,
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('ConnectorConfigurationLogic', () => {
expect(ConnectorConfigurationLogic.values).toEqual({
...DEFAULT_VALUES,
configState: { foo: { label: 'newBar', value: 'oldBar' } },
configView: [{ key: 'foo', label: 'newBar', value: 'oldBar' }],
configView: [{ isPasswordField: false, key: 'foo', label: 'newBar', value: 'oldBar' }],
});
});
it('should set config on setConfigState', () => {
Expand All @@ -66,7 +66,7 @@ describe('ConnectorConfigurationLogic', () => {
expect(ConnectorConfigurationLogic.values).toEqual({
...DEFAULT_VALUES,
configState: { foo: { label: 'thirdBar', value: 'fourthBar' } },
configView: [{ key: 'foo', label: 'thirdBar', value: 'fourthBar' }],
configView: [{ isPasswordField: false, key: 'foo', label: 'thirdBar', value: 'fourthBar' }],
});
});
describe('setLocalConfigEntry', () => {
Expand All @@ -92,8 +92,8 @@ describe('ConnectorConfigurationLogic', () => {
password: { label: 'thirdBar', value: 'fourthBar' },
},
configView: [
{ key: 'bar', label: 'foo', value: 'foofoo' },
{ key: 'password', label: 'thirdBar', value: 'fourthBar' },
{ isPasswordField: false, key: 'bar', label: 'foo', value: 'foofoo' },
{ isPasswordField: true, key: 'password', label: 'thirdBar', value: 'fourthBar' },
],
localConfigState: {
bar: { label: 'foo', value: 'fafa' },
Expand All @@ -112,7 +112,7 @@ describe('ConnectorConfigurationLogic', () => {
expect(ConnectorConfigurationLogic.values).toEqual({
...DEFAULT_VALUES,
configState: connectorIndex.connector.configuration,
configView: [{ key: 'foo', label: 'bar', value: 'barbar' }],
configView: [{ isPasswordField: false, key: 'foo', label: 'bar', value: 'barbar' }],
index: connectorIndex,
});
});
Expand All @@ -134,7 +134,7 @@ describe('ConnectorConfigurationLogic', () => {
expect(ConnectorConfigurationLogic.values).toEqual({
...DEFAULT_VALUES,
configState: connectorIndex.connector.configuration,
configView: [{ key: 'foo', label: 'bar', value: 'barbar' }],
configView: [{ isPasswordField: false, key: 'foo', label: 'bar', value: 'barbar' }],
index: {
...connectorIndex,
connector: { ...connectorIndex.connector, status: ConnectorStatus.NEEDS_CONFIGURATION },
Expand All @@ -155,7 +155,7 @@ describe('ConnectorConfigurationLogic', () => {
});
ConnectorConfigurationLogic.actions.saveConfig();
expect(ConnectorConfigurationLogic.actions.makeRequest).toHaveBeenCalledWith({
configuration: { foo: { label: 'bar', value: 'Barbara' } },
configuration: { foo: 'Barbara' },
connectorId: '2',
indexName: 'connector',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
import { kea, MakeLogicType } from 'kea';

import { ConnectorConfiguration, ConnectorStatus } from '../../../../../../common/types/connectors';
import { Actions } from '../../../../shared/api_logic/create_api_logic';
import { isNotNullish } from '../../../../../../common/utils/is_not_nullish';

import {
ConnectorConfigurationApiLogic,
PostConnectorConfigurationArgs,
PostConnectorConfigurationResponse,
PostConnectorConfigurationActions,
} from '../../../api/connector/update_connector_configuration_api_logic';
import {
CachedFetchIndexApiLogic,
Expand All @@ -23,7 +22,7 @@ import { FetchIndexApiResponse } from '../../../api/index/fetch_index_api_logic'
import { isConnectorIndex } from '../../../utils/indices';

type ConnectorConfigurationActions = Pick<
Actions<PostConnectorConfigurationArgs, PostConnectorConfigurationResponse>,
PostConnectorConfigurationActions,
'apiSuccess' | 'makeRequest'
> & {
fetchIndexApiSuccess: CachedFetchIndexApiLogicActions['apiSuccess'];
Expand Down Expand Up @@ -53,9 +52,40 @@ interface ConfigEntry {
isPasswordField: boolean;
key: string;
label: string;
order?: number;
value: string;
}

/**
*
* Sorts the connector configuration by specified order (if present)
* otherwise by alphabetic order of keys
*
*/
function sortConnectorConfiguration(config: ConnectorConfiguration): ConfigEntry[] {
return Object.keys(config)
.map(
(key) =>
({
key,
...config[key],
} as ConfigEntry)
)
.sort((a, b) => {
if (isNotNullish(a.order)) {
if (isNotNullish(b.order)) {
return a.order - b.order;
}
return -1;
}
if (isNotNullish(b.order)) {
// a doesn't have an order, but b has an order so takes precedence
return 1;
}
return a.key.localeCompare(b.key);
});
}

export const ConnectorConfigurationLogic = kea<
MakeLogicType<ConnectorConfigurationValues, ConnectorConfigurationActions>
>({
Expand Down Expand Up @@ -117,7 +147,17 @@ export const ConnectorConfigurationLogic = kea<
saveConfig: () => {
if (isConnectorIndex(values.index)) {
actions.makeRequest({
configuration: values.localConfigState,
configuration: Object.keys(values.localConfigState)
.map((key) =>
values.localConfigState[key]
? { key, value: values.localConfigState[key]?.value ?? '' }
: null
)
.filter(isNotNullish)
.reduce(
(prev: Record<string, string>, { key, value }) => ({ ...prev, [key]: value }),
{}
),
connectorId: values.index.connector.id,
indexName: values.index.connector.index_name,
});
Expand Down Expand Up @@ -148,9 +188,9 @@ export const ConnectorConfigurationLogic = kea<
localConfigState: [
{},
{
setLocalConfigEntry: (configState, { key, label, value }) => ({
setLocalConfigEntry: (configState, { key, label, order, value }) => ({
...configState,
[key]: { label, value },
[key]: { label, order, value },
}),
setLocalConfigState: (_, { configState }) => configState,
},
Expand All @@ -166,27 +206,21 @@ export const ConnectorConfigurationLogic = kea<
selectors: ({ selectors }) => ({
configView: [
() => [selectors.configState],
(configState) =>
Object.keys(configState)
.map((key) => ({
key,
label: configState[key].label,
value: configState[key].value,
}))
.sort((a, b) => a.key.localeCompare(b.key)),
(configState: ConnectorConfiguration) =>
sortConnectorConfiguration(configState).map((config) => ({
...config,
isPasswordField:
config.key.includes('password') || config.label.toLowerCase().includes('password'),
})),
],
localConfigView: [
() => [selectors.localConfigState],
(configState) =>
Object.keys(configState)
.map((key) => ({
isPasswordField:
key.includes('password') || configState[key].label.toLowerCase().includes('password'),
key,
label: configState[key].label,
value: configState[key].value,
}))
.sort((a, b) => a.key.localeCompare(b.key)),
sortConnectorConfiguration(configState).map((config) => ({
...config,
isPasswordField:
config.key.includes('password') || config.label.toLowerCase().includes('password'),
})),
],
}),
});
Loading

0 comments on commit 61bd0c8

Please sign in to comment.