From 9674128105e5ebe73de926ea720ee48dcc346881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:57:17 +0100 Subject: [PATCH] [Console] Add a dev config for the editor migration (#176520) ## Summary This PR adds a dev config to Console to enable a migration to the Monaco editor. The config value is `false` by default and can be changed by adding `console.dev.enableMonaco: true` to `kibana.dev.yml`. Also a new custom Monaco language is registered for Console in the package `kbn/monaco` and will be worked on behind the config flag iteratively in the next weeks. To not let the dev config get into 8.13 release, this PR will only be merged **after** 8.13 has been branched. After this PR is merged, the team will start re-implementing existing Console features in the new Monaco editor, see https://github.com/elastic/kibana/issues/176723 and https://github.com/elastic/kibana/issues/176926 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-monaco/index.ts | 2 + packages/kbn-monaco/src/console/constants.ts | 9 +++ packages/kbn-monaco/src/console/index.ts | 10 ++++ packages/kbn-monaco/src/console/language.ts | 60 +++++++++++++++++++ packages/kbn-monaco/src/register_globals.ts | 2 + .../application/containers/editor/editor.tsx | 4 ++ .../editor/monaco/monaco_editor.tsx | 25 ++++++++ .../contexts/services_context.mock.ts | 3 + .../application/contexts/services_context.tsx | 3 + .../console/public/application/index.tsx | 5 ++ src/plugins/console/public/plugin.ts | 2 + src/plugins/console/public/types/config.ts | 3 + src/plugins/console/server/config.ts | 2 + src/plugins/console/tsconfig.json | 2 + .../test_suites/core_plugins/rendering.ts | 1 + 15 files changed, 133 insertions(+) create mode 100644 packages/kbn-monaco/src/console/constants.ts create mode 100644 packages/kbn-monaco/src/console/index.ts create mode 100644 packages/kbn-monaco/src/console/language.ts create mode 100644 src/plugins/console/public/application/containers/editor/monaco/monaco_editor.tsx diff --git a/packages/kbn-monaco/index.ts b/packages/kbn-monaco/index.ts index c764bc679c1ab..49f93e85e77d1 100644 --- a/packages/kbn-monaco/index.ts +++ b/packages/kbn-monaco/index.ts @@ -31,3 +31,5 @@ import { registerLanguage } from './src/helpers'; export { BarePluginApi, registerLanguage }; export * from './src/types'; + +export { CONSOLE_LANG_ID } from './src/console'; diff --git a/packages/kbn-monaco/src/console/constants.ts b/packages/kbn-monaco/src/console/constants.ts new file mode 100644 index 0000000000000..b777e6eb22532 --- /dev/null +++ b/packages/kbn-monaco/src/console/constants.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export const CONSOLE_LANG_ID = 'console'; diff --git a/packages/kbn-monaco/src/console/index.ts b/packages/kbn-monaco/src/console/index.ts new file mode 100644 index 0000000000000..ba35b66f2156f --- /dev/null +++ b/packages/kbn-monaco/src/console/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export { CONSOLE_LANG_ID } from './constants'; +export { ConsoleLang } from './language'; diff --git a/packages/kbn-monaco/src/console/language.ts b/packages/kbn-monaco/src/console/language.ts new file mode 100644 index 0000000000000..77c795d76d9ea --- /dev/null +++ b/packages/kbn-monaco/src/console/language.ts @@ -0,0 +1,60 @@ +/* + * 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 { LangModuleType } from '../types'; +import { CONSOLE_LANG_ID } from './constants'; +import { monaco } from '../monaco_imports'; + +export const languageConfiguration: monaco.languages.LanguageConfiguration = {}; + +export const lexerRules: monaco.languages.IMonarchLanguage = { + defaultToken: 'invalid', + regex_method: /get|post|put|patch|delete/, + regex_url: /.*$/, + // C# style strings + escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, + ignoreCase: true, + tokenizer: { + root: [ + // whitespace + { include: '@rule_whitespace' }, + // start a multi-line comment + { include: '@rule_start_multi_comment' }, + // a one-line comment + [/\/\/.*$/, 'comment'], + // method + [/@regex_method/, 'keyword'], + // url + [/@regex_url/, 'identifier'], + ], + rule_whitespace: [[/[ \t\r\n]+/, 'WHITESPACE']], + rule_start_multi_comment: [[/\/\*/, 'comment', '@rule_multi_comment']], + rule_multi_comment: [ + // match everything on a single line inside the comment except for chars / and * + [/[^\/*]+/, 'comment'], + // start a nested comment by going 1 level down + [/\/\*/, 'comment', '@push'], + // match the closing of the comment and return 1 level up + ['\\*/', 'comment', '@pop'], + // match individual chars inside a multi-line comment + [/[\/*]/, 'comment'], + ], + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }], + ], + }, +}; + +export const ConsoleLang: LangModuleType = { + ID: CONSOLE_LANG_ID, + lexerRules, + languageConfiguration, +}; diff --git a/packages/kbn-monaco/src/register_globals.ts b/packages/kbn-monaco/src/register_globals.ts index 159563a8d0d9c..5483c5d377194 100644 --- a/packages/kbn-monaco/src/register_globals.ts +++ b/packages/kbn-monaco/src/register_globals.ts @@ -13,6 +13,7 @@ import { monaco } from './monaco_imports'; import { ESQL_THEME_ID, ESQLLang, buildESQlTheme } from './esql'; import { YAML_LANG_ID } from './yaml'; import { registerLanguage, registerTheme } from './helpers'; +import { ConsoleLang } from './console'; export const DEFAULT_WORKER_ID = 'default'; const langSpecificWorkerIds = [ @@ -30,6 +31,7 @@ registerLanguage(XJsonLang); registerLanguage(PainlessLang); registerLanguage(SQLLang); registerLanguage(ESQLLang); +registerLanguage(ConsoleLang); /** * Register custom themes diff --git a/src/plugins/console/public/application/containers/editor/editor.tsx b/src/plugins/console/public/application/containers/editor/editor.tsx index 788039a2dc606..580232048b28f 100644 --- a/src/plugins/console/public/application/containers/editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/editor.tsx @@ -16,6 +16,7 @@ import { Editor as EditorUI, EditorOutput } from './legacy/console_editor'; import { getAutocompleteInfo, StorageKeys } from '../../../services'; import { useEditorReadContext, useServicesContext, useRequestReadContext } from '../../contexts'; import type { SenseEditor } from '../../models'; +import { MonacoEditor } from './monaco/monaco_editor'; const INITIAL_PANEL_WIDTH = 50; const PANEL_MIN_WIDTH = '100px'; @@ -28,6 +29,7 @@ interface Props { export const Editor = memo(({ loading, setEditorInstance }: Props) => { const { services: { storage }, + config: { isMonacoEnabled } = {}, } = useServicesContext(); const { currentTextObject } = useEditorReadContext(); @@ -71,6 +73,8 @@ export const Editor = memo(({ loading, setEditorInstance }: Props) => { > {loading ? ( + ) : isMonacoEnabled ? ( + ) : ( { + const [value, setValue] = useState('GET /.kibana/_search'); + return ( +
+ +
+ ); +}; diff --git a/src/plugins/console/public/application/contexts/services_context.mock.ts b/src/plugins/console/public/application/contexts/services_context.mock.ts index 5d3c7ea6e172d..f02a6df5ff996 100644 --- a/src/plugins/console/public/application/contexts/services_context.mock.ts +++ b/src/plugins/console/public/application/contexts/services_context.mock.ts @@ -44,6 +44,9 @@ export const serviceContextMock = { docLinkVersion: 'NA', theme$: themeServiceMock.create().start().theme$, docLinks: docLinksServiceMock.createStartContract().links, + config: { + isMonacoEnabled: false, + }, }; }, }; diff --git a/src/plugins/console/public/application/contexts/services_context.tsx b/src/plugins/console/public/application/contexts/services_context.tsx index a9fb86175d02c..d2c91e7c73604 100644 --- a/src/plugins/console/public/application/contexts/services_context.tsx +++ b/src/plugins/console/public/application/contexts/services_context.tsx @@ -32,6 +32,9 @@ export interface ContextValue { docLinkVersion: string; theme$: Observable; docLinks: DocLinksStart['links']; + config?: { + isMonacoEnabled: boolean; + }; } interface ContextProps { diff --git a/src/plugins/console/public/application/index.tsx b/src/plugins/console/public/application/index.tsx index 83ee337fdac1e..e211e1557476a 100644 --- a/src/plugins/console/public/application/index.tsx +++ b/src/plugins/console/public/application/index.tsx @@ -43,6 +43,7 @@ export interface BootDependencies { theme$: Observable; docLinks: DocLinksStart['links']; autocompleteInfo: AutocompleteInfo; + isMonacoEnabled: boolean; } export async function renderApp({ @@ -55,6 +56,7 @@ export async function renderApp({ theme$, docLinks, autocompleteInfo, + isMonacoEnabled, }: BootDependencies) { const trackUiMetric = createUsageTracker(usageCollection); trackUiMetric.load('opened_app'); @@ -92,6 +94,9 @@ export async function renderApp({ autocompleteInfo, }, theme$, + config: { + isMonacoEnabled, + }, }} > diff --git a/src/plugins/console/public/plugin.ts b/src/plugins/console/public/plugin.ts index ca097322486ea..45a28e0e0c445 100644 --- a/src/plugins/console/public/plugin.ts +++ b/src/plugins/console/public/plugin.ts @@ -34,6 +34,7 @@ export class ConsoleUIPlugin implements Plugin(); this.autocompleteInfo.setup(http); @@ -83,6 +84,7 @@ export class ConsoleUIPlugin implements Plugin = { exposeToBrowser: { ui: true, autocompleteDefinitions: true, + dev: true, }, schema: schemaLatest, deprecations: () => [], diff --git a/src/plugins/console/tsconfig.json b/src/plugins/console/tsconfig.json index 925cef9cbbbab..28583a28bfcde 100644 --- a/src/plugins/console/tsconfig.json +++ b/src/plugins/console/tsconfig.json @@ -27,6 +27,8 @@ "@kbn/core-elasticsearch-server", "@kbn/core-http-browser-mocks", "@kbn/react-kibana-context-theme", + "@kbn/code-editor", + "@kbn/monaco", ], "exclude": [ "target/**/*", diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index e6434471a08cf..d58da62a8a956 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -101,6 +101,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { // When plugin owners make a change that exposes additional config values, the changes will be reflected in this test assertion. // Ensure that your change does not unintentionally expose any sensitive values! 'console.autocompleteDefinitions.endpointsAvailability (alternatives)', + 'console.dev.enableMonaco (boolean)', 'console.ui.enabled (boolean)', 'console.ui.embeddedEnabled (boolean)', 'dashboard.allowByValueEmbeddables (boolean)',