Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Console Monaco migration] Implement history #183181

Merged
merged 35 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
00533b2
[Console] Implement method and url path autocomplete
yuliacech Apr 22, 2024
6f2911b
[Console] Tests
yuliacech Apr 23, 2024
cc4f6ae
[Console] Implement url params autocomplete
yuliacech Apr 24, 2024
084e274
[Console] Implement body params autocomplete suggestions
yuliacech Apr 30, 2024
2562e53
[Console] Fix merge conflict issues
yuliacech May 3, 2024
0485996
[Console] Fix merge conflict issues
yuliacech May 3, 2024
5e17ca1
[Console] Remove console log
yuliacech May 3, 2024
80f801d
[Console] Add template
yuliacech May 3, 2024
eb7f43c
Merge branch 'main' into console/implement_autocomplete_body
yuliacech May 6, 2024
fc47ebd
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine May 6, 2024
b00fa24
[Console] Clean up tests
yuliacech May 6, 2024
3e0d610
[Console] Fix imports
yuliacech May 7, 2024
9e192d1
[Console] Fix tokens parsing for nested objects
yuliacech May 7, 2024
a911984
Merge branch 'main' into console/implement_autocomplete_body
yuliacech May 8, 2024
c1b393d
[Console] Start migrating the console history to monaco
yuliacech May 8, 2024
1abcc66
[Console] Implement console history in monaco
yuliacech May 10, 2024
28bf9b7
Merge branch 'main' into console/migrate_history
yuliacech May 15, 2024
8c03ef3
[Console] Remove unused imports
yuliacech May 15, 2024
4c172b5
[Console] Fixed the new line insertion
yuliacech May 15, 2024
aa86dcf
Merge branch 'main' into console/migrate_history
yuliacech May 15, 2024
9c33bfe
Merge branch 'main' into console/migrate_history
yuliacech May 15, 2024
511722d
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine May 15, 2024
48c0fb6
[Console] Add comments
yuliacech May 15, 2024
cb83b15
Merge branch 'main' into console/migrate_history
yuliacech May 16, 2024
42ff316
[Console] Fix types
yuliacech May 16, 2024
a7cfd66
[Console] Fix types
yuliacech May 16, 2024
7f93171
[Console] Fix an issue when inserting a history request
yuliacech May 17, 2024
77495e0
Merge branch 'main' into console/migrate_history
yuliacech May 17, 2024
ca60bbc
[Console] Add unit tests
yuliacech May 17, 2024
5f6ed4e
Merge branch 'main' into console/migrate_history
yuliacech May 21, 2024
dc2e42e
Merge branch 'main' into console/migrate_history
yuliacech May 21, 2024
67968c6
[Console] Fix inserting the history request on a line outside of a pa…
yuliacech May 21, 2024
c4e0741
Merge branch 'main' into console/migrate_history
yuliacech May 22, 2024
fb2b7dc
[Console] Fix merge conflict issues
yuliacech May 22, 2024
f5ae554
[Console] Fix eslint issues
yuliacech May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {

import { useServicesContext } from '../../contexts';
import { HistoryViewer } from './history_viewer';
import { HistoryViewer as HistoryViewerMonaco } from './history_viewer_monaco';
import { useEditorReadContext } from '../../contexts/editor_context';
import { useRestoreRequestFromHistory } from '../../hooks';

Expand All @@ -35,6 +36,7 @@ const CHILD_ELEMENT_PREFIX = 'historyReq';
export function ConsoleHistory({ close }: Props) {
const {
services: { history },
config: { isMonacoEnabled },
} = useServicesContext();

const { settings: readOnlySettings } = useEditorReadContext();
Expand Down Expand Up @@ -91,7 +93,7 @@ export function ConsoleHistory({ close }: Props) {
initialize();
};

const restoreRequestFromHistory = useRestoreRequestFromHistory();
const restoreRequestFromHistory = useRestoreRequestFromHistory(isMonacoEnabled);

useEffect(() => {
initialize();
Expand Down Expand Up @@ -181,7 +183,11 @@ export function ConsoleHistory({ close }: Props) {

<div className="conHistory__body__spacer" />

<HistoryViewer settings={readOnlySettings} req={viewingReq} />
{isMonacoEnabled ? (
<HistoryViewerMonaco settings={readOnlySettings} req={viewingReq} />
) : (
<HistoryViewer settings={readOnlySettings} req={viewingReq} />
)}
</div>

<EuiSpacer size="s" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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 React, { useCallback, useRef } from 'react';
import { css } from '@emotion/react';
import { CONSOLE_LANG_ID, CONSOLE_THEME_ID, monaco } from '@kbn/monaco';
import { CodeEditor } from '@kbn/code-editor';
import { i18n } from '@kbn/i18n';
import { formatRequestBodyDoc } from '../../../lib/utils';
import { DevToolsSettings } from '../../../services';
import { useResizeCheckerUtils } from '../editor/monaco/hooks';

export const HistoryViewer = ({
settings,
req,
}: {
settings: DevToolsSettings;
req: { method: string; endpoint: string; data: string; time: string } | null;
}) => {
const divRef = useRef<HTMLDivElement | null>(null);
const { setupResizeChecker, destroyResizeChecker } = useResizeCheckerUtils();

const editorDidMountCallback = useCallback(
(editor: monaco.editor.IStandaloneCodeEditor) => {
setupResizeChecker(divRef.current!, editor);
},
[setupResizeChecker]
);

const editorWillUnmountCallback = useCallback(() => {
destroyResizeChecker();
}, [destroyResizeChecker]);
let renderedHistoryRequest: string;
if (req) {
const indent = true;
const formattedData = req.data ? formatRequestBodyDoc([req.data], indent).data : '';
renderedHistoryRequest = req.method + ' ' + req.endpoint + '\n' + formattedData;
} else {
renderedHistoryRequest = i18n.translate('console.historyPage.noHistoryTextMessage', {
defaultMessage: 'No history available',
});
}
return (
<div
css={css`
width: 100%;
`}
ref={divRef}
>
<CodeEditor
languageId={CONSOLE_LANG_ID}
value={renderedHistoryRequest}
fullWidth={true}
editorDidMount={editorDidMountCallback}
editorWillUnmount={editorWillUnmountCallback}
options={{
readOnly: true,
fontSize: settings.fontSize,
wordWrap: settings.wrapMode ? 'on' : 'off',
theme: CONSOLE_THEME_ID,
automaticLayout: true,
}}
/>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface SetInitialValueParams {
/**
* Util function for reading the load_from parameter from the current url.
*/

export const readLoadFromParam = () => {
const [, queryString] = (window.location.hash || window.location.search || '').split('?');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { css } from '@emotion/react';
import { CodeEditor } from '@kbn/code-editor';
import { CONSOLE_LANG_ID, CONSOLE_THEME_ID, monaco } from '@kbn/monaco';
import { i18n } from '@kbn/i18n';
import { useSetInputEditor } from '../../../hooks';
import { ConsoleMenu } from '../../../components';
import {
useServicesContext,
Expand All @@ -33,17 +34,11 @@ export interface EditorProps {
}

export const MonacoEditor = ({ initialTextValue }: EditorProps) => {
const context = useServicesContext();
const {
services: {
notifications,
esHostService,
trackUiMetric,
http,
settings: settingsService,
autocompleteInfo,
},
services: { notifications, esHostService, settings: settingsService, autocompleteInfo },
docLinkVersion,
} = useServicesContext();
} = context;
const { toasts } = notifications;
const { settings } = useEditorReadContext();

Expand All @@ -55,6 +50,7 @@ export const MonacoEditor = ({ initialTextValue }: EditorProps) => {
const actionsProvider = useRef<MonacoEditorActionsProvider | null>(null);
const [editorActionsCss, setEditorActionsCss] = useState<CSSProperties>({});

const setInputEditor = useSetInputEditor();
const getCurlCallback = useCallback(async (): Promise<string> => {
const curl = await actionsProvider.current?.getCurl(esHostService.getHost());
return curl ?? '';
Expand All @@ -69,12 +65,14 @@ export const MonacoEditor = ({ initialTextValue }: EditorProps) => {
}, []);

const sendRequestsCallback = useCallback(async () => {
await actionsProvider.current?.sendRequests(toasts, dispatch, trackUiMetric, http);
}, [dispatch, http, toasts, trackUiMetric]);
await actionsProvider.current?.sendRequests(dispatch, context);
}, [dispatch, context]);

const editorDidMountCallback = useCallback(
(editor: monaco.editor.IStandaloneCodeEditor) => {
actionsProvider.current = new MonacoEditorActionsProvider(editor, setEditorActionsCss);
const provider = new MonacoEditorActionsProvider(editor, setEditorActionsCss);
setInputEditor(provider);
actionsProvider.current = provider;
setupResizeChecker(divRef.current!, editor);
registerKeyboardCommands({
editor,
Expand All @@ -86,7 +84,13 @@ export const MonacoEditor = ({ initialTextValue }: EditorProps) => {
moveToNextRequestEdge: async () => await actionsProvider.current?.moveToNextRequestEdge(),
});
},
[getDocumenationLink, registerKeyboardCommands, sendRequestsCallback, setupResizeChecker]
[
getDocumenationLink,
registerKeyboardCommands,
sendRequestsCallback,
setupResizeChecker,
setInputEditor,
]
);

const editorWillUnmountCallback = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ describe('Editor actions provider', () => {
getPosition: jest.fn(),
getTopForLineNumber: jest.fn(),
getScrollTop: jest.fn(),
executeEdits: jest.fn(),
setPosition: jest.fn(),
} as unknown as jest.Mocked<monaco.editor.IStandaloneCodeEditor>;

Expand Down Expand Up @@ -401,4 +402,160 @@ describe('Editor actions provider', () => {
});
});
});

describe('restoreRequestFromHistory', () => {
const testHistoryRequest = 'GET _alias';
beforeEach(() => {
/*
* The editor has the text
* "POST _search" on line 1
* { "test": "test" } on lines 2-4
* and "GET _analyze" on line 5
*/
mockGetParsedRequests.mockReturnValue([
{
startOffset: 0,
method: 'POST',
url: '_search',
endOffset: 35,
data: [
{
test: 'test',
},
],
},
{
startOffset: 36,
method: 'GET',
url: '_analyze',
endOffset: 48,
},
]);

editor.getModel.mockReturnValue({
getLineMaxColumn: (lineNumber: number) => {
// mock this function for line 4
return 2;
},
getPositionAt: (offset: number) => {
// mock this function for start offsets of the mocked requests
if (offset === 0) {
return { lineNumber: 1, column: 1 };
}
if (offset === 36) {
return { lineNumber: 5, column: 1 };
}
// mock this function for end offsets of the mocked requests
if (offset === 35) {
return { lineNumber: 4, column: 2 };
}
if (offset === 48) {
return { lineNumber: 5, column: 13 };
}
},
getLineContent: (lineNumber: number) => {
// mock this functions for line 1 and line 2
if (lineNumber === 1) {
return 'POST _search';
}
if (lineNumber === 2) {
return '{';
}
if (lineNumber === 3) {
return ' "test": "test"';
}
if (lineNumber === 4) {
return '}';
}
if (lineNumber === 5) {
return 'GET _analyze';
}
},
} as unknown as monaco.editor.ITextModel);
});

it('insert the request at the beginning of the selected request', async () => {
// the position of the cursor is in the middle of line 5
editor.getPosition.mockReturnValue({
lineNumber: 5,
column: 4,
} as monaco.Position);
editor.getSelection.mockReturnValue({
startLineNumber: 5,
endLineNumber: 5,
} as monaco.Selection);

await editorActionsProvider.restoreRequestFromHistory(testHistoryRequest);
const expectedRange = {
startLineNumber: 5,
startColumn: 1,
endLineNumber: 5,
endColumn: 1,
};
const expectedText = testHistoryRequest + '\n';
const expectedEdit = {
range: expectedRange,
text: expectedText,
forceMoveMarkers: true,
};
expect(editor.executeEdits).toHaveBeenCalledTimes(1);
expect(editor.executeEdits).toHaveBeenCalledWith('restoreFromHistory', [expectedEdit]);
});

it('insert the request at the end of the selected request', async () => {
// the position of the cursor is at the end of line 4
editor.getPosition.mockReturnValue({
lineNumber: 4,
column: 2,
} as monaco.Position);
editor.getSelection.mockReturnValue({
startLineNumber: 4,
endLineNumber: 4,
} as monaco.Selection);
await editorActionsProvider.restoreRequestFromHistory(testHistoryRequest);
const expectedRange = {
startLineNumber: 4,
startColumn: 2,
endLineNumber: 4,
endColumn: 2,
};
const expectedText = '\n' + testHistoryRequest;
const expectedEdit = {
range: expectedRange,
text: expectedText,
forceMoveMarkers: true,
};
expect(editor.executeEdits).toHaveBeenCalledTimes(1);
expect(editor.executeEdits).toHaveBeenCalledWith('restoreFromHistory', [expectedEdit]);
});

it('insert at the beginning of the line, if no selected request', async () => {
// mock no parsed requests
mockGetParsedRequests.mockReturnValue([]);
// the position of the cursor is at the end of line 4
editor.getPosition.mockReturnValue({
lineNumber: 4,
column: 2,
} as monaco.Position);
editor.getSelection.mockReturnValue({
startLineNumber: 4,
endLineNumber: 4,
} as monaco.Selection);
await editorActionsProvider.restoreRequestFromHistory(testHistoryRequest);
const expectedRange = {
startLineNumber: 4,
startColumn: 1,
endLineNumber: 4,
endColumn: 1,
};
const expectedText = testHistoryRequest + '\n';
const expectedEdit = {
range: expectedRange,
text: expectedText,
forceMoveMarkers: true,
};
expect(editor.executeEdits).toHaveBeenCalledTimes(1);
expect(editor.executeEdits).toHaveBeenCalledWith('restoreFromHistory', [expectedEdit]);
});
});
});
Loading