>;
// @public
export interface ICspConfig {
@@ -1840,26 +1870,14 @@ export interface RegisterDeprecationsConfig {
export type RequestHandler = (context: Context, request: KibanaRequest
, response: ResponseFactory) => IKibanaResponse | Promise>;
// @public
-export interface RequestHandlerContext {
+export interface RequestHandlerContext extends RequestHandlerContextBase {
// (undocumented)
- core: {
- savedObjects: {
- client: SavedObjectsClientContract;
- typeRegistry: ISavedObjectTypeRegistry;
- getClient: (options?: SavedObjectsClientProviderOptions) => SavedObjectsClientContract;
- getExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter;
- getImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter;
- };
- elasticsearch: {
- client: IScopedClusterClient;
- };
- uiSettings: {
- client: IUiSettingsClient;
- };
- deprecations: {
- client: DeprecationsClient;
- };
- };
+ core: Promise;
+}
+
+// @public (undocumented)
+export interface RequestHandlerContextBase {
+ resolve: >(parts: T[]) => Promise>>;
}
// @public
diff --git a/src/core/server/server.ts b/src/core/server/server.ts
index fc215d905581..c73e98f4bb6c 100644
--- a/src/core/server/server.ts
+++ b/src/core/server/server.ts
@@ -42,7 +42,6 @@ import { config as uiSettingsConfig } from './ui_settings';
import { config as statusConfig } from './status';
import { config as i18nConfig } from './i18n';
import { ContextService } from './context';
-import { RequestHandlerContext } from '.';
import {
InternalCorePreboot,
InternalCoreSetup,
@@ -372,13 +371,9 @@ export class Server {
}
private registerCoreContext(coreSetup: InternalCoreSetup) {
- coreSetup.http.registerRouteHandlerContext(
- coreId,
- 'core',
- (context, req, res): RequestHandlerContext['core'] => {
- return new CoreRouteHandlerContext(this.coreStart!, req);
- }
- );
+ coreSetup.http.registerRouteHandlerContext(coreId, 'core', async (context, req, res) => {
+ return new CoreRouteHandlerContext(this.coreStart!, req);
+ });
}
public setupCoreConfig() {
diff --git a/src/core/server/ui_settings/routes/delete.ts b/src/core/server/ui_settings/routes/delete.ts
index f8ab4d5d0c2c..87c6edf38642 100644
--- a/src/core/server/ui_settings/routes/delete.ts
+++ b/src/core/server/ui_settings/routes/delete.ts
@@ -23,7 +23,7 @@ export function registerDeleteRoute(router: IRouter) {
{ path: '/api/kibana/settings/{key}', validate },
async (context, request, response) => {
try {
- const uiSettingsClient = context.core.uiSettings.client;
+ const uiSettingsClient = (await context.core).uiSettings.client;
await uiSettingsClient.remove(request.params.key);
diff --git a/src/core/server/ui_settings/routes/get.ts b/src/core/server/ui_settings/routes/get.ts
index 051d562c3980..0929330cf023 100644
--- a/src/core/server/ui_settings/routes/get.ts
+++ b/src/core/server/ui_settings/routes/get.ts
@@ -14,7 +14,7 @@ export function registerGetRoute(router: IRouter) {
{ path: '/api/kibana/settings', validate: false },
async (context, request, response) => {
try {
- const uiSettingsClient = context.core.uiSettings.client;
+ const uiSettingsClient = (await context.core).uiSettings.client;
return response.ok({
body: {
settings: await uiSettingsClient.getUserProvided(),
diff --git a/src/core/server/ui_settings/routes/set.ts b/src/core/server/ui_settings/routes/set.ts
index 7de287f4ebe6..91518fb6f347 100644
--- a/src/core/server/ui_settings/routes/set.ts
+++ b/src/core/server/ui_settings/routes/set.ts
@@ -26,7 +26,7 @@ export function registerSetRoute(router: IRouter) {
{ path: '/api/kibana/settings/{key}', validate },
async (context, request, response) => {
try {
- const uiSettingsClient = context.core.uiSettings.client;
+ const uiSettingsClient = (await context.core).uiSettings.client;
const { key } = request.params;
const { value } = request.body;
diff --git a/src/core/server/ui_settings/routes/set_many.ts b/src/core/server/ui_settings/routes/set_many.ts
index c4053dd3e7ee..f4f3f509bf92 100644
--- a/src/core/server/ui_settings/routes/set_many.ts
+++ b/src/core/server/ui_settings/routes/set_many.ts
@@ -21,7 +21,7 @@ const validate = {
export function registerSetManyRoute(router: IRouter) {
router.post({ path: '/api/kibana/settings', validate }, async (context, request, response) => {
try {
- const uiSettingsClient = context.core.uiSettings.client;
+ const uiSettingsClient = (await context.core).uiSettings.client;
const { changes } = request.body;
diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
index fbf6d64170ee..ca81383ba639 100755
--- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
+++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker
@@ -40,6 +40,11 @@ kibana_vars=(
csp.report_to
data.autocomplete.valueSuggestions.terminateAfter
data.autocomplete.valueSuggestions.timeout
+ unifiedSearch.autocomplete.valueSuggestions.terminateAfter
+ unifiedSearch.autocomplete.valueSuggestions.timeout
+ unifiedSearch.autocomplete.querySuggestions.enabled
+ unifiedSearch.autocomplete.valueSuggestions.enabled
+ unifiedSearch.autocomplete.valueSuggestions.tiers
elasticsearch.customHeaders
elasticsearch.hosts
elasticsearch.logQueries
diff --git a/src/plugins/console/common/constants/api.ts b/src/plugins/console/common/constants/api.ts
index aa0fad1fe442..3c5aa1151935 100644
--- a/src/plugins/console/common/constants/api.ts
+++ b/src/plugins/console/common/constants/api.ts
@@ -7,3 +7,4 @@
*/
export const API_BASE_PATH = '/api/console';
+export const KIBANA_API_PREFIX = 'kbn:';
diff --git a/src/plugins/console/common/constants/index.ts b/src/plugins/console/common/constants/index.ts
index d8768af8fc8d..756a79883cbd 100644
--- a/src/plugins/console/common/constants/index.ts
+++ b/src/plugins/console/common/constants/index.ts
@@ -7,4 +7,4 @@
*/
export { MAJOR_VERSION } from './plugin';
-export { API_BASE_PATH } from './api';
+export { API_BASE_PATH, KIBANA_API_PREFIX } from './api';
diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.mock.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.mock.tsx
index dfed86a64362..b410e240151d 100644
--- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.mock.tsx
+++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.mock.tsx
@@ -39,8 +39,8 @@ jest.mock('../../../../models/sense_editor', () => {
};
});
-jest.mock('../../../../hooks/use_send_current_request_to_es/send_request_to_es', () => ({
- sendRequestToES: jest.fn(),
+jest.mock('../../../../hooks/use_send_current_request/send_request', () => ({
+ sendRequest: jest.fn(),
}));
jest.mock('../../../../../lib/autocomplete/get_endpoint_from_position', () => ({
getEndpointFromPosition: jest.fn(),
diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.tsx
index b942a6d83021..ba5f1e78d5f0 100644
--- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.tsx
+++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.test.tsx
@@ -25,7 +25,7 @@ import {
} from '../../../../contexts';
// Mocked functions
-import { sendRequestToES } from '../../../../hooks/use_send_current_request_to_es/send_request_to_es';
+import { sendRequest } from '../../../../hooks/use_send_current_request/send_request';
import { getEndpointFromPosition } from '../../../../../lib/autocomplete/get_endpoint_from_position';
import type { DevToolsSettings } from '../../../../../services';
import * as consoleMenuActions from '../console_menu_actions';
@@ -58,15 +58,15 @@ describe('Legacy (Ace) Console Editor Component Smoke Test', () => {
sandbox.restore();
});
- it('calls send current request to ES', async () => {
+ it('calls send current request', async () => {
(getEndpointFromPosition as jest.Mock).mockReturnValue({ patterns: [] });
- (sendRequestToES as jest.Mock).mockRejectedValue({});
+ (sendRequest as jest.Mock).mockRejectedValue({});
const editor = doMount();
act(() => {
editor.find('button[data-test-subj~="sendRequestButton"]').simulate('click');
});
await nextTick();
- expect(sendRequestToES).toBeCalledTimes(1);
+ expect(sendRequest).toBeCalledTimes(1);
});
it('opens docs', () => {
diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx
index bafe9ee6ca15..d01a40bdd44b 100644
--- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx
+++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx
@@ -26,7 +26,7 @@ import { ConsoleMenu } from '../../../../components';
import { useEditorReadContext, useServicesContext } from '../../../../contexts';
import {
useSaveCurrentTextObject,
- useSendCurrentRequestToES,
+ useSendCurrentRequest,
useSetInputEditor,
} from '../../../../hooks';
import * as senseEditor from '../../../../models/sense_editor';
@@ -72,7 +72,7 @@ function EditorUI({ initialTextValue, setEditorInstance }: EditorProps) {
const { settings } = useEditorReadContext();
const setInputEditor = useSetInputEditor();
- const sendCurrentRequestToES = useSendCurrentRequestToES();
+ const sendCurrentRequest = useSendCurrentRequest();
const saveCurrentTextObject = useSaveCurrentTextObject();
const editorRef = useRef(null);
@@ -231,11 +231,11 @@ function EditorUI({ initialTextValue, setEditorInstance }: EditorProps) {
if (!isKeyboardShortcutsDisabled) {
registerCommands({
senseEditor: editorInstanceRef.current!,
- sendCurrentRequestToES,
+ sendCurrentRequest,
openDocumentation,
});
}
- }, [sendCurrentRequestToES, openDocumentation, settings]);
+ }, [openDocumentation, settings, sendCurrentRequest]);
useEffect(() => {
const { current: editor } = editorInstanceRef;
@@ -262,7 +262,7 @@ function EditorUI({ initialTextValue, setEditorInstance }: EditorProps) {
>
void;
+ sendCurrentRequest: () => void;
openDocumentation: () => void;
}
@@ -24,11 +24,7 @@ const COMMANDS = {
GO_TO_LINE: 'gotoline',
};
-export function registerCommands({
- senseEditor,
- sendCurrentRequestToES,
- openDocumentation,
-}: Actions) {
+export function registerCommands({ senseEditor, sendCurrentRequest, openDocumentation }: Actions) {
const throttledAutoIndent = throttle(() => senseEditor.autoIndent(), 500, {
leading: true,
trailing: true,
@@ -39,7 +35,7 @@ export function registerCommands({
keys: { win: 'Ctrl-Enter', mac: 'Command-Enter' },
name: COMMANDS.SEND_TO_ELASTICSEARCH,
fn: () => {
- sendCurrentRequestToES();
+ sendCurrentRequest();
},
});
diff --git a/src/plugins/console/public/application/hooks/index.ts b/src/plugins/console/public/application/hooks/index.ts
index 1a9b4e5c472b..1996330bef66 100644
--- a/src/plugins/console/public/application/hooks/index.ts
+++ b/src/plugins/console/public/application/hooks/index.ts
@@ -8,6 +8,6 @@
export { useSetInputEditor } from './use_set_input_editor';
export { useRestoreRequestFromHistory } from './use_restore_request_from_history';
-export { useSendCurrentRequestToES } from './use_send_current_request_to_es';
+export { useSendCurrentRequest } from './use_send_current_request';
export { useSaveCurrentTextObject } from './use_save_current_text_object';
export { useDataInit } from './use_data_init';
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/index.ts b/src/plugins/console/public/application/hooks/use_send_current_request/index.ts
similarity index 81%
rename from src/plugins/console/public/application/hooks/use_send_current_request_to_es/index.ts
rename to src/plugins/console/public/application/hooks/use_send_current_request/index.ts
index df2431f1f6f4..33bdbef87f2e 100644
--- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/index.ts
+++ b/src/plugins/console/public/application/hooks/use_send_current_request/index.ts
@@ -6,4 +6,4 @@
* Side Public License, v 1.
*/
-export { useSendCurrentRequestToES } from './use_send_current_request_to_es';
+export { useSendCurrentRequest } from './use_send_current_request';
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.test.ts b/src/plugins/console/public/application/hooks/use_send_current_request/send_request.test.ts
similarity index 66%
rename from src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.test.ts
rename to src/plugins/console/public/application/hooks/use_send_current_request/send_request.test.ts
index 8578e271f37b..60ced085c689 100644
--- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.test.ts
+++ b/src/plugins/console/public/application/hooks/use_send_current_request/send_request.test.ts
@@ -8,14 +8,14 @@
import type { ContextValue } from '../../contexts';
-jest.mock('./send_request_to_es', () => ({ sendRequestToES: jest.fn(() => Promise.resolve()) }));
+jest.mock('./send_request', () => ({ sendRequest: jest.fn(() => Promise.resolve()) }));
-import { sendRequestToES } from './send_request_to_es';
+import { sendRequest } from './send_request';
import { serviceContextMock } from '../../contexts/services_context.mock';
-const mockedSendRequestToES = sendRequestToES as jest.Mock;
+const mockedSendRequest = sendRequest as jest.Mock;
-describe('sendRequestToES', () => {
+describe('sendRequest', () => {
let mockContextValue: ContextValue;
beforeEach(() => {
@@ -26,8 +26,8 @@ describe('sendRequestToES', () => {
jest.resetAllMocks();
});
- it('should send request to ES', async () => {
- mockedSendRequestToES.mockResolvedValue([
+ it('should send request', async () => {
+ mockedSendRequest.mockResolvedValue([
{
response: {
statusCode: 200,
@@ -40,17 +40,17 @@ describe('sendRequestToES', () => {
http: mockContextValue.services.http,
requests: [{ method: 'PUT', url: 'test', data: [] }],
};
- const results = await sendRequestToES(args);
+ const results = await sendRequest(args);
const [request] = results;
expect(request.response.statusCode).toEqual(200);
expect(request.response.value).toContain('"acknowledged": true');
- expect(mockedSendRequestToES).toHaveBeenCalledWith(args);
- expect(mockedSendRequestToES).toHaveBeenCalledTimes(1);
+ expect(mockedSendRequest).toHaveBeenCalledWith(args);
+ expect(mockedSendRequest).toHaveBeenCalledTimes(1);
});
- it('should send multiple requests to ES', async () => {
- mockedSendRequestToES.mockResolvedValue([
+ it('should send multiple requests', async () => {
+ mockedSendRequest.mockResolvedValue([
{
response: {
statusCode: 200,
@@ -70,17 +70,17 @@ describe('sendRequestToES', () => {
{ method: 'GET', url: 'test-2', data: [] },
],
};
- const results = await sendRequestToES(args);
+ const results = await sendRequest(args);
const [firstRequest, secondRequest] = results;
expect(firstRequest.response.statusCode).toEqual(200);
expect(secondRequest.response.statusCode).toEqual(200);
- expect(mockedSendRequestToES).toHaveBeenCalledWith(args);
- expect(mockedSendRequestToES).toHaveBeenCalledTimes(1);
+ expect(mockedSendRequest).toHaveBeenCalledWith(args);
+ expect(mockedSendRequest).toHaveBeenCalledTimes(1);
});
it('should handle errors', async () => {
- mockedSendRequestToES.mockRejectedValue({
+ mockedSendRequest.mockRejectedValue({
response: {
statusCode: 500,
statusText: 'error',
@@ -88,45 +88,46 @@ describe('sendRequestToES', () => {
});
try {
- await sendRequestToES({
+ await sendRequest({
http: mockContextValue.services.http,
requests: [{ method: 'GET', url: 'test', data: [] }],
});
} catch (error) {
expect(error.response.statusCode).toEqual(500);
expect(error.response.statusText).toEqual('error');
- expect(mockedSendRequestToES).toHaveBeenCalledTimes(1);
+ expect(mockedSendRequest).toHaveBeenCalledTimes(1);
}
});
+
describe('successful response value', () => {
describe('with text', () => {
it('should return value with lines separated', async () => {
- mockedSendRequestToES.mockResolvedValue('\ntest_index-1 [] \ntest_index-2 []\n');
- const response = await sendRequestToES({
+ mockedSendRequest.mockResolvedValue('\ntest_index-1 []\ntest_index-2 []\n');
+ const response = await sendRequest({
http: mockContextValue.services.http,
requests: [{ method: 'GET', url: 'test-1', data: [] }],
});
expect(response).toMatchInlineSnapshot(`
"
- test_index-1 []
+ test_index-1 []
test_index-2 []
"
`);
- expect(mockedSendRequestToES).toHaveBeenCalledTimes(1);
+ expect(mockedSendRequest).toHaveBeenCalledTimes(1);
});
});
describe('with parsed json', () => {
it('should stringify value', async () => {
- mockedSendRequestToES.mockResolvedValue(JSON.stringify({ test: 'some value' }));
- const response = await sendRequestToES({
+ mockedSendRequest.mockResolvedValue(JSON.stringify({ test: 'some value' }));
+ const response = await sendRequest({
http: mockContextValue.services.http,
requests: [{ method: 'GET', url: 'test-2', data: [] }],
});
expect(typeof response).toBe('string');
- expect(mockedSendRequestToES).toHaveBeenCalledTimes(1);
+ expect(mockedSendRequest).toHaveBeenCalledTimes(1);
});
});
});
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request/send_request.ts
similarity index 69%
rename from src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts
rename to src/plugins/console/public/application/hooks/use_send_current_request/send_request.ts
index 451198aaf2d2..1247f3f78aa6 100644
--- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/send_request_to_es.ts
+++ b/src/plugins/console/public/application/hooks/use_send_current_request/send_request.ts
@@ -15,12 +15,12 @@ import { BaseResponseType } from '../../../types';
const { collapseLiteralStrings } = XJson;
-export interface EsRequestArgs {
+export interface RequestArgs {
http: HttpSetup;
requests: Array<{ url: string; method: string; data: string[] }>;
}
-export interface ESResponseObject {
+export interface ResponseObject {
statusCode: number;
statusText: string;
timeMs: number;
@@ -28,17 +28,17 @@ export interface ESResponseObject {
value: V;
}
-export interface ESRequestResult {
+export interface RequestResult {
request: { data: string; method: string; path: string };
- response: ESResponseObject;
+ response: ResponseObject;
}
let CURRENT_REQ_ID = 0;
-export function sendRequestToES(args: EsRequestArgs): Promise {
+export function sendRequest(args: RequestArgs): Promise {
const requests = args.requests.slice();
return new Promise((resolve, reject) => {
const reqId = ++CURRENT_REQ_ID;
- const results: ESRequestResult[] = [];
+ const results: RequestResult[] = [];
if (reqId !== CURRENT_REQ_ID) {
return;
}
@@ -59,11 +59,11 @@ export function sendRequestToES(args: EsRequestArgs): Promise
return;
}
const req = requests.shift()!;
- const esPath = req.url;
- const esMethod = req.method;
- let esData = collapseLiteralStrings(req.data.join('\n'));
- if (esData) {
- esData += '\n';
+ const path = req.url;
+ const method = req.method;
+ let data = collapseLiteralStrings(req.data.join('\n'));
+ if (data) {
+ data += '\n';
} // append a new line for bulk requests.
const startTime = Date.now();
@@ -71,9 +71,9 @@ export function sendRequestToES(args: EsRequestArgs): Promise
try {
const { response, body } = await es.send({
http: args.http,
- method: esMethod,
- path: esPath,
- data: esData,
+ method,
+ path,
+ data,
asResponse: true,
});
@@ -115,9 +115,9 @@ export function sendRequestToES(args: EsRequestArgs): Promise
value,
},
request: {
- data: esData,
- method: esMethod,
- path: esPath,
+ data,
+ method,
+ path,
},
});
@@ -127,25 +127,19 @@ export function sendRequestToES(args: EsRequestArgs): Promise
}
} catch (error) {
let value;
- let contentType: string | null = '';
+ const { response, body } = error as IHttpFetchError;
+ const contentType = response?.headers.get('Content-Type') ?? '';
+ const statusCode = response?.status ?? 500;
+ const statusText = error?.response?.statusText ?? 'error';
- const { response, body = {} } = error as IHttpFetchError;
- if (response) {
- const { status, headers } = response;
- if (body) {
- value = JSON.stringify(body, null, 2); // ES error should be shown
- contentType = headers.get('Content-Type');
- } else {
- value = 'Request failed to get to the server (status code: ' + status + ')';
- contentType = headers.get('Content-Type');
- }
-
- if (isMultiRequest) {
- value = '# ' + req.method + ' ' + req.url + '\n' + value;
- }
+ if (body) {
+ value = JSON.stringify(body, null, 2);
} else {
- value =
- "\n\nFailed to connect to Console's backend.\nPlease check the Kibana server is up and running";
+ value = 'Request failed to get to the server (status code: ' + statusCode + ')';
+ }
+
+ if (isMultiRequest) {
+ value = '# ' + req.method + ' ' + req.url + '\n' + value;
}
reject({
@@ -153,13 +147,13 @@ export function sendRequestToES(args: EsRequestArgs): Promise
value,
contentType,
timeMs: Date.now() - startTime,
- statusCode: error?.response?.status ?? 500,
- statusText: error?.response?.statusText ?? 'error',
+ statusCode,
+ statusText,
},
request: {
- data: esData,
- method: esMethod,
- path: esPath,
+ data,
+ method,
+ path,
},
});
}
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/track.ts b/src/plugins/console/public/application/hooks/use_send_current_request/track.ts
similarity index 100%
rename from src/plugins/console/public/application/hooks/use_send_current_request_to_es/track.ts
rename to src/plugins/console/public/application/hooks/use_send_current_request/track.ts
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.test.tsx b/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.test.tsx
similarity index 80%
rename from src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.test.tsx
rename to src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.test.tsx
index e0131dc116a3..d16dc3f832d3 100644
--- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.test.tsx
+++ b/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.test.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-jest.mock('./send_request_to_es', () => ({ sendRequestToES: jest.fn() }));
+jest.mock('./send_request', () => ({ sendRequest: jest.fn() }));
jest.mock('../../contexts/editor_context/editor_registry', () => ({
instance: { getInputEditor: jest.fn() },
}));
@@ -21,10 +21,10 @@ import { serviceContextMock } from '../../contexts/services_context.mock';
import { useRequestActionContext } from '../../contexts/request_context';
import { instance as editorRegistry } from '../../contexts/editor_context/editor_registry';
-import { sendRequestToES } from './send_request_to_es';
-import { useSendCurrentRequestToES } from './use_send_current_request_to_es';
+import { sendRequest } from './send_request';
+import { useSendCurrentRequest } from './use_send_current_request';
-describe('useSendCurrentRequestToES', () => {
+describe('useSendCurrentRequest', () => {
let mockContextValue: ContextValue;
let dispatch: (...args: unknown[]) => void;
const contexts = ({ children }: { children: JSX.Element }) => (
@@ -41,18 +41,18 @@ describe('useSendCurrentRequestToES', () => {
jest.resetAllMocks();
});
- it('calls send request to ES', async () => {
+ it('calls send request', async () => {
// Set up mocks
(mockContextValue.services.settings.toJSON as jest.Mock).mockReturnValue({});
// This request should succeed
- (sendRequestToES as jest.Mock).mockResolvedValue([]);
+ (sendRequest as jest.Mock).mockResolvedValue([]);
(editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
getRequestsInRange: () => ['test'],
}));
- const { result } = renderHook(() => useSendCurrentRequestToES(), { wrapper: contexts });
+ const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
await act(() => result.current());
- expect(sendRequestToES).toHaveBeenCalledWith({
+ expect(sendRequest).toHaveBeenCalledWith({
http: mockContextValue.services.http,
requests: ['test'],
});
@@ -64,12 +64,12 @@ describe('useSendCurrentRequestToES', () => {
it('handles known errors', async () => {
// Set up mocks
- (sendRequestToES as jest.Mock).mockRejectedValue({ response: 'nada' });
+ (sendRequest as jest.Mock).mockRejectedValue({ response: 'nada' });
(editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
getRequestsInRange: () => ['test'],
}));
- const { result } = renderHook(() => useSendCurrentRequestToES(), { wrapper: contexts });
+ const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
await act(() => result.current());
// Second call should be the request failure
const [, [requestFailedCall]] = (dispatch as jest.Mock).mock.calls;
@@ -80,12 +80,12 @@ describe('useSendCurrentRequestToES', () => {
it('handles unknown errors', async () => {
// Set up mocks
- (sendRequestToES as jest.Mock).mockRejectedValue(NaN /* unexpected error value */);
+ (sendRequest as jest.Mock).mockRejectedValue(NaN /* unexpected error value */);
(editorRegistry.getInputEditor as jest.Mock).mockImplementation(() => ({
getRequestsInRange: () => ['test'],
}));
- const { result } = renderHook(() => useSendCurrentRequestToES(), { wrapper: contexts });
+ const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
await act(() => result.current());
// Second call should be the request failure
const [, [requestFailedCall]] = (dispatch as jest.Mock).mock.calls;
@@ -100,7 +100,7 @@ describe('useSendCurrentRequestToES', () => {
it('notifies the user about save to history errors once only', async () => {
// Set up mocks
- (sendRequestToES as jest.Mock).mockReturnValue(
+ (sendRequest as jest.Mock).mockReturnValue(
[{ request: {} }, { request: {} }] /* two responses to save history */
);
(mockContextValue.services.settings.toJSON as jest.Mock).mockReturnValue({});
@@ -112,7 +112,7 @@ describe('useSendCurrentRequestToES', () => {
getRequestsInRange: () => ['test', 'test'],
}));
- const { result } = renderHook(() => useSendCurrentRequestToES(), { wrapper: contexts });
+ const { result } = renderHook(() => useSendCurrentRequest(), { wrapper: contexts });
await act(() => result.current());
expect(dispatch).toHaveBeenCalledTimes(2);
diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.ts
similarity index 96%
rename from src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts
rename to src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.ts
index e7c436c9806b..ed08304d8d66 100644
--- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts
+++ b/src/plugins/console/public/application/hooks/use_send_current_request/use_send_current_request.ts
@@ -16,10 +16,10 @@ import { retrieveAutoCompleteInfo } from '../../../lib/mappings/mappings';
import { instance as registry } from '../../contexts/editor_context/editor_registry';
import { useRequestActionContext, useServicesContext } from '../../contexts';
import { StorageQuotaError } from '../../components/storage_quota_error';
-import { sendRequestToES } from './send_request_to_es';
+import { sendRequest } from './send_request';
import { track } from './track';
-export const useSendCurrentRequestToES = () => {
+export const useSendCurrentRequest = () => {
const {
services: { history, settings, notifications, trackUiMetric, http },
theme$,
@@ -46,7 +46,7 @@ export const useSendCurrentRequestToES = () => {
// Fire and forget
setTimeout(() => track(requests, editor, trackUiMetric), 0);
- const results = await sendRequestToES({ http, requests });
+ const results = await sendRequest({ http, requests });
let saveToHistoryError: undefined | Error;
const { isHistoryDisabled } = settings.toJSON();
diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js
index 0889b98c6938..ff9d245f6127 100644
--- a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js
+++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js
@@ -455,11 +455,11 @@ describe('Editor', () => {
editorInput1,
{ start: { lineNumber: 7 }, end: { lineNumber: 14 } },
`
-curl -XGET "http://localhost:9200/_stats?level=shards"
+curl -XGET "http://localhost:9200/_stats?level=shards" -H "kbn-xsrf: reporting"
#in between comment
-curl -XPUT "http://localhost:9200/index_1/type1/1" -H 'Content-Type: application/json' -d'
+curl -XPUT "http://localhost:9200/index_1/type1/1" -H "kbn-xsrf: reporting" -H "Content-Type: application/json" -d'
{
"f": 1
}'`.trim()
@@ -470,7 +470,7 @@ curl -XPUT "http://localhost:9200/index_1/type1/1" -H 'Content-Type: application
editorInput1,
{ start: { lineNumber: 29 }, end: { lineNumber: 33 } },
`
-curl -XPOST "http://localhost:9200/_sql?format=txt" -H 'Content-Type: application/json' -d'
+curl -XPOST "http://localhost:9200/_sql?format=txt" -H "kbn-xsrf: reporting" -H "Content-Type: application/json" -d'
{
"query": "SELECT prenom FROM claude_index WHERE prenom = '\\''claude'\\'' ",
"fetch_size": 1
diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts
index 5e8ca35f287b..ac65afce2c18 100644
--- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts
+++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts
@@ -14,7 +14,7 @@ import RowParser from '../../../lib/row_parser';
import * as utils from '../../../lib/utils';
// @ts-ignore
-import * as es from '../../../lib/es/es';
+import { constructUrl } from '../../../lib/es/es';
import { CoreEditor, Position, Range } from '../../../types';
import { createTokenIterator } from '../../factories';
@@ -467,21 +467,22 @@ export class SenseEditor {
return req;
}
- const esPath = req.url;
- const esMethod = req.method;
- const esData = req.data;
+ const path = req.url;
+ const method = req.method;
+ const data = req.data;
// this is the first url defined in elasticsearch.hosts
- const url = es.constructESUrl(elasticsearchBaseUrl, esPath);
+ const url = constructUrl(elasticsearchBaseUrl, path);
- let ret = 'curl -X' + esMethod + ' "' + url + '"';
- if (esData && esData.length) {
- ret += " -H 'Content-Type: application/json' -d'\n";
- const dataAsString = collapseLiteralStrings(esData.join('\n'));
+ // Append 'kbn-xsrf' header to bypass (XSRF/CSRF) protections
+ let ret = `curl -X${method.toUpperCase()} "${url}" -H "kbn-xsrf: reporting"`;
+ if (data && data.length) {
+ ret += ` -H "Content-Type: application/json" -d'\n`;
+ const dataAsString = collapseLiteralStrings(data.join('\n'));
// We escape single quoted strings that that are wrapped in single quoted strings
ret += dataAsString.replace(/'/g, "'\\''");
- if (esData.length > 1) {
+ if (data.length > 1) {
ret += '\n';
} // end with a new line
ret += "'";
diff --git a/src/plugins/console/public/application/stores/request.ts b/src/plugins/console/public/application/stores/request.ts
index 099ab24326d3..8056ab5a7987 100644
--- a/src/plugins/console/public/application/stores/request.ts
+++ b/src/plugins/console/public/application/stores/request.ts
@@ -10,18 +10,18 @@ import { Reducer } from 'react';
import { produce } from 'immer';
import { identity } from 'fp-ts/lib/function';
import { BaseResponseType } from '../../types/common';
-import { ESRequestResult } from '../hooks/use_send_current_request_to_es/send_request_to_es';
+import { RequestResult } from '../hooks/use_send_current_request/send_request';
export type Actions =
| { type: 'sendRequest'; payload: undefined }
- | { type: 'requestSuccess'; payload: { data: ESRequestResult[] } }
- | { type: 'requestFail'; payload: ESRequestResult | undefined };
+ | { type: 'requestSuccess'; payload: { data: RequestResult[] } }
+ | { type: 'requestFail'; payload: RequestResult | undefined };
export interface Store {
requestInFlight: boolean;
lastResult: {
- data: ESRequestResult[] | null;
- error?: ESRequestResult;
+ data: RequestResult[] | null;
+ error?: RequestResult;
};
}
diff --git a/src/plugins/console/public/lib/es/es.ts b/src/plugins/console/public/lib/es/es.ts
index 2a4059d664e6..10d0ad95b049 100644
--- a/src/plugins/console/public/lib/es/es.ts
+++ b/src/plugins/console/public/lib/es/es.ts
@@ -6,8 +6,9 @@
* Side Public License, v 1.
*/
-import type { HttpFetchOptions, HttpResponse, HttpSetup } from '@kbn/core/public';
-import { API_BASE_PATH } from '../../../common/constants';
+import type { HttpResponse, HttpSetup } from '@kbn/core/public';
+import { trimStart } from 'lodash';
+import { API_BASE_PATH, KIBANA_API_PREFIX } from '../../../common/constants';
const esVersion: string[] = [];
@@ -20,7 +21,7 @@ export function getContentType(body: unknown) {
return 'application/json';
}
-interface SendProps {
+interface SendConfig {
http: HttpSetup;
method: string;
path: string;
@@ -30,6 +31,8 @@ interface SendProps {
asResponse?: boolean;
}
+type Method = 'get' | 'post' | 'delete' | 'put' | 'patch' | 'head';
+
export async function send({
http,
method,
@@ -38,18 +41,48 @@ export async function send({
asSystemRequest = false,
withProductOrigin = false,
asResponse = false,
-}: SendProps) {
- const options: HttpFetchOptions = {
+}: SendConfig) {
+ const kibanaRequestUrl = getKibanaRequestUrl(path);
+
+ if (kibanaRequestUrl) {
+ const httpMethod = method.toLowerCase() as Method;
+ const url = new URL(kibanaRequestUrl);
+ const { pathname, searchParams } = url;
+ const query = Object.fromEntries(searchParams.entries());
+ const body = ['post', 'put', 'patch'].includes(httpMethod) ? data : null;
+
+ return await http[httpMethod](pathname, {
+ body,
+ query,
+ asResponse,
+ asSystemRequest,
+ });
+ }
+
+ return await http.post(`${API_BASE_PATH}/proxy`, {
query: { path, method, ...(withProductOrigin && { withProductOrigin }) },
body: data,
asResponse,
asSystemRequest,
- };
+ });
+}
+
+function getKibanaRequestUrl(path: string) {
+ const isKibanaApiRequest = path.startsWith(KIBANA_API_PREFIX);
+ const kibanaBasePath = window.location.origin;
- return await http.post(`${API_BASE_PATH}/proxy`, options);
+ if (isKibanaApiRequest) {
+ // window.location.origin is used as a Kibana public base path for sending requests in cURL commands. E.g. "Copy as cURL".
+ return `${kibanaBasePath}/${trimStart(path.replace(KIBANA_API_PREFIX, ''), '/')}`;
+ }
}
-export function constructESUrl(baseUri: string, path: string) {
+export function constructUrl(baseUri: string, path: string) {
+ const kibanaRequestUrl = getKibanaRequestUrl(path);
+
+ if (kibanaRequestUrl) {
+ return kibanaRequestUrl;
+ }
baseUri = baseUri.replace(/\/+$/, '');
path = path.replace(/^\/+/, '');
return baseUri + '/' + path;
diff --git a/src/plugins/console/public/lib/es/index.ts b/src/plugins/console/public/lib/es/index.ts
index 61d34ba96ec0..f83893e93713 100644
--- a/src/plugins/console/public/lib/es/index.ts
+++ b/src/plugins/console/public/lib/es/index.ts
@@ -6,4 +6,4 @@
* Side Public License, v 1.
*/
-export { send, constructESUrl, getContentType, getVersion } from './es';
+export { send, constructUrl, getContentType, getVersion } from './es';
diff --git a/src/plugins/controls/common/control_types/options_list/types.ts b/src/plugins/controls/common/control_types/options_list/types.ts
index 9c051e4ca623..0f889bed7bac 100644
--- a/src/plugins/controls/common/control_types/options_list/types.ts
+++ b/src/plugins/controls/common/control_types/options_list/types.ts
@@ -8,14 +8,11 @@
import { BoolQuery } from '@kbn/es-query';
import { FieldSpec } from '@kbn/data-views-plugin/common';
-import { ControlInput } from '../../types';
+import { DataControlInput } from '../../types';
export const OPTIONS_LIST_CONTROL = 'optionsListControl';
-export interface OptionsListEmbeddableInput extends ControlInput {
- fieldName: string;
- dataViewId: string;
-
+export interface OptionsListEmbeddableInput extends DataControlInput {
selectedOptions?: string[];
singleSelect?: boolean;
loading?: boolean;
diff --git a/src/plugins/controls/common/control_types/range_slider/types.ts b/src/plugins/controls/common/control_types/range_slider/types.ts
index e63ec0337a57..a975fdd27ac3 100644
--- a/src/plugins/controls/common/control_types/range_slider/types.ts
+++ b/src/plugins/controls/common/control_types/range_slider/types.ts
@@ -6,14 +6,12 @@
* Side Public License, v 1.
*/
-import { ControlInput } from '../../types';
+import { DataControlInput } from '../../types';
export const RANGE_SLIDER_CONTROL = 'rangeSliderControl';
export type RangeValue = [string, string];
-export interface RangeSliderEmbeddableInput extends ControlInput {
- fieldName: string;
- dataViewId: string;
+export interface RangeSliderEmbeddableInput extends DataControlInput {
value: RangeValue;
}
diff --git a/src/plugins/controls/common/control_types/time_slider/types.ts b/src/plugins/controls/common/control_types/time_slider/types.ts
index 73d364da80ca..31272380becd 100644
--- a/src/plugins/controls/common/control_types/time_slider/types.ts
+++ b/src/plugins/controls/common/control_types/time_slider/types.ts
@@ -6,12 +6,10 @@
* Side Public License, v 1.
*/
-import { ControlInput } from '../../types';
+import { DataControlInput } from '../../types';
export const TIME_SLIDER_CONTROL = 'timeSlider';
-export interface TimeSliderControlEmbeddableInput extends ControlInput {
- fieldName: string;
- dataViewId: string;
+export interface TimeSliderControlEmbeddableInput extends DataControlInput {
value?: [number | null, number | null];
}
diff --git a/src/plugins/controls/common/types.ts b/src/plugins/controls/common/types.ts
index 3715198d7cfe..abb24299e818 100644
--- a/src/plugins/controls/common/types.ts
+++ b/src/plugins/controls/common/types.ts
@@ -27,3 +27,8 @@ export type ControlInput = EmbeddableInput & {
controlStyle?: ControlStyle;
ignoreParentSettings?: ParentIgnoreSettings;
};
+
+export type DataControlInput = ControlInput & {
+ fieldName: string;
+ dataViewId: string;
+};
diff --git a/src/plugins/controls/kibana.json b/src/plugins/controls/kibana.json
index 20afd63505a7..e87af3f517af 100644
--- a/src/plugins/controls/kibana.json
+++ b/src/plugins/controls/kibana.json
@@ -17,7 +17,8 @@
"expressions",
"embeddable",
"dataViews",
- "data"
+ "data",
+ "unifiedSearch"
],
"optionalPlugins": []
}
diff --git a/src/plugins/controls/public/__stories__/controls.stories.tsx b/src/plugins/controls/public/__stories__/controls.stories.tsx
index 74d0d3e9de6a..481016af72a3 100644
--- a/src/plugins/controls/public/__stories__/controls.stories.tsx
+++ b/src/plugins/controls/public/__stories__/controls.stories.tsx
@@ -31,7 +31,7 @@ import { decorators } from './decorators';
import { ControlsPanels } from '../control_group/types';
import { ControlGroupContainer } from '../control_group';
import { pluginServices, registry } from '../services/storybook';
-import { replaceValueSuggestionMethod } from '../services/storybook/data';
+import { replaceValueSuggestionMethod } from '../services/storybook/unified_search';
import { injectStorybookDataView } from '../services/storybook/data_views';
import { populateStorybookControlFactories } from './storybook_control_factories';
import { OptionsListRequest } from '../services/options_list';
diff --git a/src/plugins/controls/public/control_types/range_slider/range_slider.component.tsx b/src/plugins/controls/public/control_types/range_slider/range_slider.component.tsx
index f1002290eab3..259b6bd7f66a 100644
--- a/src/plugins/controls/public/control_types/range_slider/range_slider.component.tsx
+++ b/src/plugins/controls/public/control_types/range_slider/range_slider.component.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-import React, { FC, useCallback, useState } from 'react';
+import React, { FC, useCallback } from 'react';
import { BehaviorSubject } from 'rxjs';
import { DataViewField } from '@kbn/data-views-plugin/public';
@@ -45,16 +45,13 @@ export const RangeSliderComponent: FC = ({ componentStateSubject }) => {
componentStateSubject.getValue()
);
- const { value = ['', ''], id, title } = useEmbeddableSelector((state) => state);
-
- const [selectedValue, setSelectedValue] = useState(value || ['', '']);
+ const { value, id, title } = useEmbeddableSelector((state) => state);
const onChangeComplete = useCallback(
(range: RangeValue) => {
dispatch(selectRange(range));
- setSelectedValue(range);
},
- [selectRange, setSelectedValue, dispatch]
+ [selectRange, dispatch]
);
return (
@@ -64,7 +61,7 @@ export const RangeSliderComponent: FC = ({ componentStateSubject }) => {
min={min}
max={max}
title={title}
- value={selectedValue}
+ value={value ?? ['', '']}
onChange={onChangeComplete}
fieldFormatter={fieldFormatter}
/>
diff --git a/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable.tsx b/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable.tsx
index 2777f45d026b..1ad34fd361ac 100644
--- a/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable.tsx
+++ b/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable.tsx
@@ -311,7 +311,7 @@ export class RangeSliderEmbeddable extends Embeddable {
+ public reload = () => {
this.fetchMinMax();
};
diff --git a/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable_factory.tsx b/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable_factory.tsx
index 74bb2d23dbd8..bd8b8a394988 100644
--- a/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable_factory.tsx
+++ b/src/plugins/controls/public/control_types/range_slider/range_slider_embeddable_factory.tsx
@@ -37,8 +37,8 @@ export class RangeSliderEmbeddableFactory
) => {
if (
embeddable &&
- (!deepEqual(newInput.fieldName, embeddable.getInput().fieldName) ||
- !deepEqual(newInput.dataViewId, embeddable.getInput().dataViewId))
+ ((newInput.fieldName && !deepEqual(newInput.fieldName, embeddable.getInput().fieldName)) ||
+ (newInput.dataViewId && !deepEqual(newInput.dataViewId, embeddable.getInput().dataViewId)))
) {
// if the field name or data view id has changed in this editing session, selected values are invalid, so reset them.
newInput.value = ['', ''];
diff --git a/src/plugins/controls/public/control_types/time_slider/time_slider.tsx b/src/plugins/controls/public/control_types/time_slider/time_slider.tsx
index 61a47d8779a1..d25d4f145a99 100644
--- a/src/plugins/controls/public/control_types/time_slider/time_slider.tsx
+++ b/src/plugins/controls/public/control_types/time_slider/time_slider.tsx
@@ -6,7 +6,7 @@
* Side Public License, v 1.
*/
-import React, { FC, useCallback, useState, useMemo } from 'react';
+import React, { FC, useCallback, useMemo } from 'react';
import { BehaviorSubject } from 'rxjs';
import { debounce } from 'lodash';
import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public';
@@ -59,10 +59,6 @@ export const TimeSlider: FC = ({
const { value } = useEmbeddableSelector((state) => state);
- const [selectedValue, setSelectedValue] = useState<[number | null, number | null]>(
- value || [null, null]
- );
-
const dispatchChange = useCallback(
(range: [number | null, number | null]) => {
dispatch(selectRange(range));
@@ -75,15 +71,14 @@ export const TimeSlider: FC = ({
const onChangeComplete = useCallback(
(range: [number | null, number | null]) => {
debouncedDispatchChange(range);
- setSelectedValue(range);
},
- [setSelectedValue, debouncedDispatchChange]
+ [debouncedDispatchChange]
);
return (
{
if (
embeddable &&
- (!deepEqual(newInput.fieldName, embeddable.getInput().fieldName) ||
- !deepEqual(newInput.dataViewId, embeddable.getInput().dataViewId))
+ ((newInput.fieldName && !deepEqual(newInput.fieldName, embeddable.getInput().fieldName)) ||
+ (newInput.dataViewId && !deepEqual(newInput.dataViewId, embeddable.getInput().dataViewId)))
) {
// if the field name or data view id has changed in this editing session, selected options are invalid, so reset them.
newInput.value = undefined;
diff --git a/src/plugins/controls/public/services/data.ts b/src/plugins/controls/public/services/data.ts
index 74c30a1f6d70..4e9db3b68e90 100644
--- a/src/plugins/controls/public/services/data.ts
+++ b/src/plugins/controls/public/services/data.ts
@@ -24,7 +24,6 @@ export interface ControlsDataService {
) => Observable<{ min?: number; max?: number }>;
getDataView: DataPublicPluginStart['dataViews']['get'];
getDataView$: (id: string) => Observable;
- autocomplete: DataPublicPluginStart['autocomplete'];
query: DataPublicPluginStart['query'];
searchSource: DataPublicPluginStart['search']['searchSource'];
timefilter: DataPublicPluginStart['query']['timefilter']['timefilter'];
diff --git a/src/plugins/controls/public/services/index.ts b/src/plugins/controls/public/services/index.ts
index cf358dac8b48..ac2e8374ad06 100644
--- a/src/plugins/controls/public/services/index.ts
+++ b/src/plugins/controls/public/services/index.ts
@@ -12,6 +12,7 @@ import { ControlsOverlaysService } from './overlays';
import { registry as stubRegistry } from './stub';
import { ControlsPluginStart } from '../types';
import { ControlsDataService } from './data';
+import { ControlsUnifiedSearchService } from './unified_search';
import { ControlsService } from './controls';
import { ControlsHTTPService } from './http';
import { ControlsOptionsListService } from './options_list';
@@ -22,6 +23,7 @@ export interface ControlsServices {
dataViews: ControlsDataViewsService;
overlays: ControlsOverlaysService;
data: ControlsDataService;
+ unifiedSearch: ControlsUnifiedSearchService;
http: ControlsHTTPService;
settings: ControlsSettingsService;
diff --git a/src/plugins/controls/public/services/kibana/data.ts b/src/plugins/controls/public/services/kibana/data.ts
index 3a36b929c7cb..29a96a98c7e7 100644
--- a/src/plugins/controls/public/services/kibana/data.ts
+++ b/src/plugins/controls/public/services/kibana/data.ts
@@ -43,7 +43,7 @@ const minMaxAgg = (field?: DataViewField) => {
export const dataServiceFactory: DataServiceFactory = ({ startPlugins }) => {
const {
- data: { query: queryPlugin, search, autocomplete },
+ data: { query: queryPlugin, search },
} = startPlugins;
const { data } = startPlugins;
@@ -95,7 +95,6 @@ export const dataServiceFactory: DataServiceFactory = ({ startPlugins }) => {
from(fetchFieldRange(dataView, fieldName, input)),
getDataView: data.dataViews.get,
getDataView$: (id: string) => from(data.dataViews.get(id)),
- autocomplete,
query: queryPlugin,
searchSource: search.searchSource,
timefilter: queryPlugin.timefilter.timefilter,
diff --git a/src/plugins/controls/public/services/kibana/index.ts b/src/plugins/controls/public/services/kibana/index.ts
index bed97091bed5..1bb8f600ecf8 100644
--- a/src/plugins/controls/public/services/kibana/index.ts
+++ b/src/plugins/controls/public/services/kibana/index.ts
@@ -22,6 +22,7 @@ import { dataServiceFactory } from './data';
import { httpServiceFactory } from './http';
import { optionsListServiceFactory } from './options_list';
import { settingsServiceFactory } from './settings';
+import { unifiedSearchServiceFactory } from './unified_search';
export const providers: PluginServiceProviders<
ControlsServices,
@@ -29,6 +30,7 @@ export const providers: PluginServiceProviders<
> = {
http: new PluginServiceProvider(httpServiceFactory),
data: new PluginServiceProvider(dataServiceFactory),
+ unifiedSearch: new PluginServiceProvider(unifiedSearchServiceFactory),
overlays: new PluginServiceProvider(overlaysServiceFactory),
dataViews: new PluginServiceProvider(dataViewsServiceFactory),
settings: new PluginServiceProvider(settingsServiceFactory),
diff --git a/src/plugins/controls/public/services/kibana/unified_search.ts b/src/plugins/controls/public/services/kibana/unified_search.ts
new file mode 100644
index 000000000000..15cb3a02ca45
--- /dev/null
+++ b/src/plugins/controls/public/services/kibana/unified_search.ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { KibanaPluginServiceFactory } from '@kbn/presentation-util-plugin/public';
+import { ControlsUnifiedSearchService } from '../unified_search';
+import { ControlsPluginStartDeps } from '../../types';
+
+export type UnifiedSearchServiceFactory = KibanaPluginServiceFactory<
+ ControlsUnifiedSearchService,
+ ControlsPluginStartDeps
+>;
+
+export const unifiedSearchServiceFactory: UnifiedSearchServiceFactory = ({ startPlugins }) => {
+ const {
+ unifiedSearch: { autocomplete },
+ } = startPlugins;
+
+ return {
+ autocomplete,
+ };
+};
diff --git a/src/plugins/controls/public/services/storybook/data.ts b/src/plugins/controls/public/services/storybook/data.ts
index 38a8d01d8c7c..5d8cacad9b7b 100644
--- a/src/plugins/controls/public/services/storybook/data.ts
+++ b/src/plugins/controls/public/services/storybook/data.ts
@@ -9,20 +9,11 @@
import { of, Observable } from 'rxjs';
import { PluginServiceFactory } from '@kbn/presentation-util-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
-import { DataViewField, DataView } from '@kbn/data-views-plugin/common';
+import { DataView } from '@kbn/data-views-plugin/common';
import { ControlsDataService } from '../data';
-let valueSuggestionMethod = ({ field, query }: { field: DataViewField; query: string }) =>
- Promise.resolve(['storybook', 'default', 'values']);
-export const replaceValueSuggestionMethod = (
- newMethod: ({ field, query }: { field: DataViewField; query: string }) => Promise
-) => (valueSuggestionMethod = newMethod);
-
export type DataServiceFactory = PluginServiceFactory;
export const dataServiceFactory: DataServiceFactory = () => ({
- autocomplete: {
- getValueSuggestions: valueSuggestionMethod,
- } as unknown as DataPublicPluginStart['autocomplete'],
query: {} as unknown as DataPublicPluginStart['query'],
searchSource: {
create: () => ({
diff --git a/src/plugins/controls/public/services/storybook/index.ts b/src/plugins/controls/public/services/storybook/index.ts
index f586063e5a33..751aaeefee9c 100644
--- a/src/plugins/controls/public/services/storybook/index.ts
+++ b/src/plugins/controls/public/services/storybook/index.ts
@@ -14,6 +14,7 @@ import {
} from '@kbn/presentation-util-plugin/public';
import { ControlsServices } from '..';
import { dataServiceFactory } from './data';
+import { unifiedSearchServiceFactory } from './unified_search';
import { overlaysServiceFactory } from './overlays';
import { dataViewsServiceFactory } from './data_views';
import { httpServiceFactory } from '../stub/http';
@@ -28,6 +29,7 @@ export const providers: PluginServiceProviders = {
dataViews: new PluginServiceProvider(dataViewsServiceFactory),
http: new PluginServiceProvider(httpServiceFactory),
data: new PluginServiceProvider(dataServiceFactory),
+ unifiedSearch: new PluginServiceProvider(unifiedSearchServiceFactory),
overlays: new PluginServiceProvider(overlaysServiceFactory),
settings: new PluginServiceProvider(settingsServiceFactory),
diff --git a/src/plugins/controls/public/services/storybook/unified_search.ts b/src/plugins/controls/public/services/storybook/unified_search.ts
new file mode 100644
index 000000000000..cb7df1bd1e48
--- /dev/null
+++ b/src/plugins/controls/public/services/storybook/unified_search.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { PluginServiceFactory } from '@kbn/presentation-util-plugin/public';
+import { DataViewField } from '@kbn/data-views-plugin/common';
+import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
+import { ControlsUnifiedSearchService } from '../unified_search';
+
+let valueSuggestionMethod = ({ field, query }: { field: DataViewField; query: string }) =>
+ Promise.resolve(['storybook', 'default', 'values']);
+export const replaceValueSuggestionMethod = (
+ newMethod: ({ field, query }: { field: DataViewField; query: string }) => Promise
+) => (valueSuggestionMethod = newMethod);
+
+export type UnifiedSearchServiceFactory = PluginServiceFactory;
+export const unifiedSearchServiceFactory: UnifiedSearchServiceFactory = () => ({
+ autocomplete: {
+ getValueSuggestions: valueSuggestionMethod,
+ } as unknown as UnifiedSearchPublicPluginStart['autocomplete'],
+});
diff --git a/src/plugins/controls/public/services/stub/index.ts b/src/plugins/controls/public/services/stub/index.ts
index 9b767496fa98..4cd138689452 100644
--- a/src/plugins/controls/public/services/stub/index.ts
+++ b/src/plugins/controls/public/services/stub/index.ts
@@ -20,6 +20,7 @@ import { dataServiceFactory } from '../storybook/data';
import { dataViewsServiceFactory } from '../storybook/data_views';
import { optionsListServiceFactory } from '../storybook/options_list';
import { settingsServiceFactory } from '../storybook/settings';
+import { unifiedSearchServiceFactory } from '../storybook/unified_search';
export const providers: PluginServiceProviders = {
http: new PluginServiceProvider(httpServiceFactory),
@@ -27,7 +28,7 @@ export const providers: PluginServiceProviders = {
overlays: new PluginServiceProvider(overlaysServiceFactory),
dataViews: new PluginServiceProvider(dataViewsServiceFactory),
settings: new PluginServiceProvider(settingsServiceFactory),
-
+ unifiedSearch: new PluginServiceProvider(unifiedSearchServiceFactory),
controls: new PluginServiceProvider(controlsServiceFactory),
optionsList: new PluginServiceProvider(optionsListServiceFactory),
};
diff --git a/src/plugins/controls/public/services/unified_search.ts b/src/plugins/controls/public/services/unified_search.ts
new file mode 100644
index 000000000000..2c69537b62d6
--- /dev/null
+++ b/src/plugins/controls/public/services/unified_search.ts
@@ -0,0 +1,13 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
+
+export interface ControlsUnifiedSearchService {
+ autocomplete: UnifiedSearchPublicPluginStart['autocomplete'];
+}
diff --git a/src/plugins/controls/public/types.ts b/src/plugins/controls/public/types.ts
index e5915262223e..d7766eb8d478 100644
--- a/src/plugins/controls/public/types.ts
+++ b/src/plugins/controls/public/types.ts
@@ -17,6 +17,7 @@ import {
} from '@kbn/embeddable-plugin/public';
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { DataView, DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
+import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import { ControlInput } from '../common/types';
import { ControlsService } from './services/controls';
@@ -70,9 +71,10 @@ export interface ControlsPluginSetupDeps {
}
export interface ControlsPluginStartDeps {
data: DataPublicPluginStart;
+ unifiedSearch: UnifiedSearchPublicPluginStart;
embeddable: EmbeddableStart;
dataViews: DataViewsPublicPluginStart;
}
// re-export from common
-export type { ControlWidth, ControlInput, ControlStyle } from '../common/types';
+export type { ControlWidth, ControlInput, DataControlInput, ControlStyle } from '../common/types';
diff --git a/src/plugins/controls/server/control_types/options_list/options_list_suggestions_route.ts b/src/plugins/controls/server/control_types/options_list/options_list_suggestions_route.ts
index 70c1db510c53..9af4800ca00f 100644
--- a/src/plugins/controls/server/control_types/options_list/options_list_suggestions_route.ts
+++ b/src/plugins/controls/server/control_types/options_list/options_list_suggestions_route.ts
@@ -14,8 +14,8 @@ import { Observable } from 'rxjs';
import { CoreSetup, ElasticsearchClient } from '@kbn/core/server';
import { getKbnServerError, reportServerError } from '@kbn/kibana-utils-plugin/server';
-import { PluginSetup as DataPluginSetup } from '@kbn/data-plugin/server';
import { FieldSpec, getFieldSubtypeNested } from '@kbn/data-views-plugin/common';
+import { PluginSetup as UnifiedSearchPluginSetup } from '@kbn/unified-search-plugin/server';
import {
OptionsListRequestBody,
OptionsListResponse,
@@ -23,7 +23,7 @@ import {
export const setupOptionsListSuggestionsRoute = (
{ http }: CoreSetup,
- getAutocompleteSettings: DataPluginSetup['autocomplete']['getAutocompleteSettings']
+ getAutocompleteSettings: UnifiedSearchPluginSetup['autocomplete']['getAutocompleteSettings']
) => {
const router = http.createRouter();
@@ -53,7 +53,7 @@ export const setupOptionsListSuggestionsRoute = (
try {
const suggestionRequest: OptionsListRequestBody = request.body;
const { index } = request.params;
- const esClient = context.core.elasticsearch.client.asCurrentUser;
+ const esClient = (await context.core).elasticsearch.client.asCurrentUser;
const suggestionsResponse = await getOptionsListSuggestions({
abortedEvent$: request.events.aborted$,
request: suggestionRequest,
diff --git a/src/plugins/controls/server/plugin.ts b/src/plugins/controls/server/plugin.ts
index 8e391e5f1ac8..cbe9d3923436 100644
--- a/src/plugins/controls/server/plugin.ts
+++ b/src/plugins/controls/server/plugin.ts
@@ -10,6 +10,7 @@ import { CoreSetup, Plugin } from '@kbn/core/server';
import { EmbeddableSetup } from '@kbn/embeddable-plugin/server';
import { PluginSetup as DataSetup } from '@kbn/data-plugin/server';
+import { PluginSetup as UnifiedSearchSetup } from '@kbn/unified-search-plugin/server';
import { setupOptionsListSuggestionsRoute } from './control_types/options_list/options_list_suggestions_route';
import { controlGroupContainerPersistableStateServiceFactory } from './control_group/control_group_container_factory';
import { optionsListPersistableStateServiceFactory } from './control_types/options_list/options_list_embeddable_factory';
@@ -18,10 +19,11 @@ import { timeSliderPersistableStateServiceFactory } from './control_types/time_s
interface SetupDeps {
embeddable: EmbeddableSetup;
data: DataSetup;
+ unifiedSearch: UnifiedSearchSetup;
}
export class ControlsPlugin implements Plugin