diff --git a/src/legacy/core_plugins/console/public/console.js b/src/legacy/core_plugins/console/public/console.js
index f5ba87722e1e1..2cb8d299d993f 100644
--- a/src/legacy/core_plugins/console/public/console.js
+++ b/src/legacy/core_plugins/console/public/console.js
@@ -27,9 +27,6 @@ require('ui/capabilities/route_setup');
require('./src/controllers/sense_controller');
require('./src/directives/sense_history');
-require('./src/directives/sense_settings');
-require('./src/directives/sense_help');
-require('./src/directives/sense_welcome');
require('./src/directives/console_menu_directive');
diff --git a/src/legacy/core_plugins/console/public/index.html b/src/legacy/core_plugins/console/public/index.html
index 71e7d6a044249..76a9f5bc42b58 100644
--- a/src/legacy/core_plugins/console/public/index.html
+++ b/src/legacy/core_plugins/console/public/index.html
@@ -1,4 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/legacy/core_plugins/console/public/src/console_menu.js b/src/legacy/core_plugins/console/public/src/components/console_menu.js
similarity index 100%
rename from src/legacy/core_plugins/console/public/src/console_menu.js
rename to src/legacy/core_plugins/console/public/src/components/console_menu.js
diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_help.js b/src/legacy/core_plugins/console/public/src/components/dev_tools_settings.ts
similarity index 78%
rename from src/legacy/core_plugins/console/public/src/directives/sense_help.js
rename to src/legacy/core_plugins/console/public/src/components/dev_tools_settings.ts
index 32149aacac388..f3fd1442ca90f 100644
--- a/src/legacy/core_plugins/console/public/src/directives/sense_help.js
+++ b/src/legacy/core_plugins/console/public/src/components/dev_tools_settings.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-require('./sense_help_example');
-import template from './help.html';
-
-require('ui/modules')
- .get('app/sense')
- .directive('senseHelp', function () {
- return {
- restrict: 'E',
- template
- };
- });
+export interface DevToolsSettings {
+ fontSize: number;
+ wrapMode: boolean;
+ autocomplete: {
+ fields: boolean;
+ indices: boolean;
+ templates: boolean;
+ };
+ polling: boolean;
+ tripleQuotes: boolean;
+}
diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_help_example.js b/src/legacy/core_plugins/console/public/src/components/editor_example.tsx
similarity index 57%
rename from src/legacy/core_plugins/console/public/src/directives/sense_help_example.js
rename to src/legacy/core_plugins/console/public/src/components/editor_example.tsx
index d27c4b39041ed..c67b2a3644570 100644
--- a/src/legacy/core_plugins/console/public/src/directives/sense_help_example.js
+++ b/src/legacy/core_plugins/console/public/src/components/editor_example.tsx
@@ -17,25 +17,31 @@
* under the License.
*/
-const SenseEditor = require('../sense_editor/editor');
+import React, { useEffect } from 'react';
+// @ts-ignore
import exampleText from 'raw-loader!./helpExample.txt';
-import { applyResizeCheckerToEditors } from '../sense_editor_resize';
+import $ from 'jquery';
+// @ts-ignore
+import SenseEditor from '../sense_editor/editor';
-require('ui/modules')
- .get('app/sense')
- .directive('senseHelpExample', function () {
- return {
- restrict: 'E',
- link: function ($scope, $el) {
- $el.text(exampleText.trim());
- $scope.editor = new SenseEditor($el);
- applyResizeCheckerToEditors($scope, $el, $scope.editor);
- $scope.editor.setReadOnly(true);
- $scope.editor.$blockScrolling = Infinity;
+interface EditorExampleProps {
+ panel: string;
+}
- $scope.$on('$destroy', function () {
- if ($scope.editor) $scope.editor.destroy();
- });
- }
+export function EditorExample(props: EditorExampleProps) {
+ const elemId = `help-example-${props.panel}`;
+
+ useEffect(() => {
+ const el = $(`#${elemId}`);
+ el.text(exampleText.trim());
+ const editor = new SenseEditor(el);
+ editor.setReadOnly(true);
+ editor.$blockScrolling = Infinity;
+
+ return () => {
+ editor.destroy();
};
- });
+ }, []);
+
+ return ;
+}
diff --git a/src/legacy/core_plugins/console/public/src/directives/helpExample.txt b/src/legacy/core_plugins/console/public/src/components/helpExample.txt
similarity index 100%
rename from src/legacy/core_plugins/console/public/src/directives/helpExample.txt
rename to src/legacy/core_plugins/console/public/src/components/helpExample.txt
diff --git a/src/legacy/core_plugins/console/public/src/components/help_panel.tsx b/src/legacy/core_plugins/console/public/src/components/help_panel.tsx
new file mode 100644
index 0000000000000..f17c2a510830c
--- /dev/null
+++ b/src/legacy/core_plugins/console/public/src/components/help_panel.tsx
@@ -0,0 +1,144 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+import {
+ EuiText,
+ EuiFlyout,
+ EuiFlyoutHeader,
+ EuiFlyoutBody,
+ EuiTitle,
+ EuiSpacer,
+} from '@elastic/eui';
+import { EditorExample } from './editor_example';
+
+interface Props {
+ onClose: () => void;
+}
+
+export function HelpPanel(props: Props) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Ctrl/Cmd + I
+ -
+
+
+ - Ctrl/Cmd + /
+ -
+
+
+ - Ctrl + Space
+ -
+
+
+ - Ctrl/Cmd + Enter
+ -
+
+
+ - Ctrl/Cmd + Up/Down
+ -
+
+
+ - Ctrl/Cmd + Alt + L
+ -
+
+
+ - Ctrl/Cmd + Option + 0
+ -
+
+
+ - Down arrow
+ -
+
+
+ - Enter/Tab
+ -
+
+
+ - Esc
+ -
+
+
+
+
+
+
+ );
+}
diff --git a/src/legacy/core_plugins/console/public/src/components/settings_modal.tsx b/src/legacy/core_plugins/console/public/src/components/settings_modal.tsx
new file mode 100644
index 0000000000000..ac540f18bff07
--- /dev/null
+++ b/src/legacy/core_plugins/console/public/src/components/settings_modal.tsx
@@ -0,0 +1,249 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useState } from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import {
+ EuiButton,
+ EuiButtonEmpty,
+ EuiFieldNumber,
+ EuiFormRow,
+ EuiCheckboxGroup,
+ EuiModal,
+ EuiModalBody,
+ EuiModalFooter,
+ EuiModalHeader,
+ EuiModalHeaderTitle,
+ EuiOverlayMask,
+ EuiSwitch,
+} from '@elastic/eui';
+import { DevToolsSettings } from './dev_tools_settings';
+
+export type AutocompleteOptions = 'fields' | 'indices' | 'templates';
+
+interface Props {
+ onSaveSettings: (newSettings: DevToolsSettings) => Promise;
+ onClose: () => void;
+ refreshAutocompleteSettings: () => void;
+ settings: DevToolsSettings;
+}
+
+export function DevToolsSettingsModal(props: Props) {
+ const [fontSize, setFontSize] = useState(props.settings.fontSize);
+ const [wrapMode, setWrapMode] = useState(props.settings.wrapMode);
+ const [fields, setFields] = useState(props.settings.autocomplete.fields);
+ const [indices, setIndices] = useState(props.settings.autocomplete.indices);
+ const [templates, setTemplates] = useState(props.settings.autocomplete.templates);
+ const [polling, setPolling] = useState(props.settings.polling);
+ const [tripleQuotes, setTripleQuotes] = useState(props.settings.tripleQuotes);
+
+ const autoCompleteCheckboxes = [
+ {
+ id: 'fields',
+ label: i18n.translate('console.settingsPage.fieldsLabelText', {
+ defaultMessage: 'Fields',
+ }),
+ stateSetter: setFields,
+ },
+ {
+ id: 'indices',
+ label: i18n.translate('console.settingsPage.indicesAndAliasesLabelText', {
+ defaultMessage: 'Indices & Aliases',
+ }),
+ stateSetter: setIndices,
+ },
+ {
+ id: 'templates',
+ label: i18n.translate('console.settingsPage.templatesLabelText', {
+ defaultMessage: 'Templates',
+ }),
+ stateSetter: setTemplates,
+ },
+ ];
+
+ const checkboxIdToSelectedMap = {
+ fields,
+ indices,
+ templates,
+ };
+
+ const onAutocompleteChange = (optionId: AutocompleteOptions) => {
+ const option = _.find(autoCompleteCheckboxes, item => item.id === optionId);
+ if (option) {
+ option.stateSetter(!checkboxIdToSelectedMap[optionId]);
+ }
+ };
+
+ function saveSettings() {
+ props.onSaveSettings({
+ fontSize,
+ wrapMode,
+ autocomplete: {
+ fields,
+ indices,
+ templates,
+ },
+ polling,
+ tripleQuotes,
+ });
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ }
+ >
+ {
+ const val = parseInt(e.target.value, 10);
+ if (!val) return;
+ setFontSize(val);
+ }}
+ />
+
+
+
+ }
+ onChange={e => setWrapMode(e.target.checked)}
+ />
+
+
+
+ }
+ >
+
+ }
+ onChange={e => setTripleQuotes(e.target.checked)}
+ />
+
+
+ }
+ >
+ {
+ onAutocompleteChange(e as AutocompleteOptions);
+ }}
+ />
+
+
+ }
+ helpText={
+
+ }
+ >
+
+ }
+ onChange={e => setPolling(e.target.checked)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/legacy/core_plugins/console/public/src/components/welcome_panel.tsx b/src/legacy/core_plugins/console/public/src/components/welcome_panel.tsx
new file mode 100644
index 0000000000000..d8e7f75d9929a
--- /dev/null
+++ b/src/legacy/core_plugins/console/public/src/components/welcome_panel.tsx
@@ -0,0 +1,134 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+// @ts-ignore
+import {
+ EuiFlyout,
+ EuiFlyoutHeader,
+ EuiFlyoutBody,
+ EuiTitle,
+ EuiButton,
+ EuiText,
+ EuiFlyoutFooter,
+} from '@elastic/eui';
+import { EditorExample } from './editor_example';
+
+interface Props {
+ onDismiss: () => void;
+}
+
+export function WelcomePanel(props: Props) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js b/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js
index ce39a005750b2..003458868f248 100644
--- a/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js
+++ b/src/legacy/core_plugins/console/public/src/controllers/sense_controller.js
@@ -23,10 +23,15 @@ import $ from 'jquery';
import { initializeInput } from '../input';
import { initializeOutput } from '../output';
import init from '../app';
-import { SenseTopNavController } from './sense_top_nav_controller';
import { getEndpointFromPosition } from '../autocomplete';
import { DOC_LINK_VERSION } from 'ui/documentation_links';
+// welcome message
+import { showWelcomePanel } from '../helpers/welcome_show_panel';
+import storage from '../storage';
+
+import { getTopNavConfig } from '../helpers/get_top_nav';
+
const module = require('ui/modules').get('app/sense');
module.run(function ($rootScope) {
@@ -35,10 +40,19 @@ module.run(function ($rootScope) {
};
});
-module.controller('SenseController', function SenseController(Private, $scope, $timeout, $location, kbnUiAceKeyboardModeService) {
+function showWelcomeMessageIfNeeded($scope) {
+ if (storage.get('version_welcome_shown') !== '@@SENSE_REVISION') {
+ const hideWelcomePanel = showWelcomePanel();
+ $scope.$on('$destroy', () => {
+ hideWelcomePanel();
+ });
+ }
+}
+
+module.controller('SenseController', function SenseController($scope, $timeout, $location, kbnUiAceKeyboardModeService) {
docTitle.change('Console');
- $scope.topNavController = Private(SenseTopNavController);
+ showWelcomeMessageIfNeeded($scope);
// Since we pass this callback via reactDirective into a react component, which has the function defined as required
// in it's prop types, we should set this initially (before it's set in the $timeout below). Without this line
@@ -85,6 +99,15 @@ module.controller('SenseController', function SenseController(Private, $scope, $
}
});
};
+
+ $scope.showHistory = false;
+ $scope.historyDirty = undefined;
+ $scope.toggleHistory = () => {
+ $scope.showHistory = !$scope.showHistory;
+ };
+
+ $scope.topNavMenu = getTopNavConfig($scope, $scope.toggleHistory);
+
$scope.openDocumentation = () => {
if (!$scope.documentation) {
return;
@@ -94,7 +117,11 @@ module.controller('SenseController', function SenseController(Private, $scope, $
$scope.sendSelected = () => {
input.focus();
- input.sendCurrentRequestToES();
+ input.sendCurrentRequestToES(() => {
+ // History watches this value and will re-render itself when it changes, so that
+ // the list of requests stays up-to-date as new requests are sent.
+ $scope.lastRequestTimestamp = new Date().getTime();
+ });
return false;
};
diff --git a/src/legacy/core_plugins/console/public/src/directives/_history.scss b/src/legacy/core_plugins/console/public/src/directives/_history.scss
index 982669b44656d..0d1e9315c3978 100644
--- a/src/legacy/core_plugins/console/public/src/directives/_history.scss
+++ b/src/legacy/core_plugins/console/public/src/directives/_history.scss
@@ -1,3 +1,7 @@
+sense-history {
+ padding: $euiSizeS;
+}
+
.conHistory__body {
display: flex;
height: $euiSizeXL * 10;
diff --git a/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.js b/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.js
index b5a1476e8f9ce..be04e6bcc17fe 100644
--- a/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.js
+++ b/src/legacy/core_plugins/console/public/src/directives/console_menu_directive.js
@@ -23,7 +23,7 @@ import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/sense', ['react']);
-import { ConsoleMenu } from '../console_menu';
+import { ConsoleMenu } from '../components/console_menu';
module.directive('consoleMenu', function (reactDirective) {
return reactDirective(wrapInI18nContext(ConsoleMenu));
diff --git a/src/legacy/core_plugins/console/public/src/directives/help.html b/src/legacy/core_plugins/console/public/src/directives/help.html
deleted file mode 100644
index 11cb5c254b9ac..0000000000000
--- a/src/legacy/core_plugins/console/public/src/directives/help.html
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_history.js b/src/legacy/core_plugins/console/public/src/directives/sense_history.js
index 178fe6e7c5dc7..dfcee2b87ba73 100644
--- a/src/legacy/core_plugins/console/public/src/directives/sense_history.js
+++ b/src/legacy/core_plugins/console/public/src/directives/sense_history.js
@@ -33,35 +33,48 @@ require('ui/modules')
restrict: 'E',
template,
controllerAs: 'history',
+ scope: {
+ isShown: '=',
+ historyDirty: '=',
+ },
controller: function ($scope, $element) {
- this.reqs = history.getHistory();
- this.selectedIndex = 0;
- this.selectedReq = this.reqs[this.selectedIndex];
- this.viewingReq = this.selectedReq;
+ $scope.$watch('historyDirty', () => {
+ this.init();
+ });
- // calculate the text description of a request
- this.describeReq = memoize((req) => {
- const endpoint = req.endpoint;
- const date = moment(req.time);
+ $scope.$watch('isShown', () => {
+ if ($scope.isShown) this.init();
+ });
- let formattedDate = date.format('MMM D');
- if (date.diff(moment(), 'days') > -7) {
- formattedDate = date.fromNow();
- }
+ this.init = () => {
+ this.reqs = history.getHistory();
+ this.selectedIndex = 0;
+ this.selectedReq = this.reqs[this.selectedIndex];
+ this.viewingReq = this.selectedReq;
- return `${endpoint} (${formattedDate})`;
- });
- this.describeReq.cache = new WeakMap();
+ // calculate the text description of a request
+ this.describeReq = memoize((req) => {
+ const endpoint = req.endpoint;
+ const date = moment(req.time);
+
+ let formattedDate = date.format('MMM D');
+ if (date.diff(moment(), 'days') > -7) {
+ formattedDate = date.fromNow();
+ }
+
+ return `${endpoint} (${formattedDate})`;
+ });
+ this.describeReq.cache = new WeakMap();
+ };
// main actions
this.clear = () => {
history.clearHistory($element);
- $scope.kbnTopNav.close();
+ this.init();
};
this.restore = (req = this.selectedReq) => {
history.restoreFromHistory(req);
- $scope.kbnTopNav.close();
};
this.onKeyDown = (ev) => {
diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_settings.js b/src/legacy/core_plugins/console/public/src/directives/sense_settings.js
deleted file mode 100644
index 9337d6f6e21fe..0000000000000
--- a/src/legacy/core_plugins/console/public/src/directives/sense_settings.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-require('ui/directives/input_focus');
-
-import template from './settings.html';
-import { getAutocomplete, getCurrentSettings, updateSettings, getPolling } from '../settings';
-import mappings from '../mappings';
-
-require('ui/modules')
- .get('app/sense')
- .directive('senseSettings', function () {
- return {
- restrict: 'E',
- template,
- controllerAs: 'settings',
- controller: function ($scope, $element) {
- this.vals = getCurrentSettings();
-
- this.isPollingVisible = () => {
- const selectedAutoCompleteOptions =
- Object.keys(this.vals.autocomplete).filter(key => this.vals.autocomplete[key]);
- return selectedAutoCompleteOptions.length > 0;
- };
-
- this.refresh = () => {
- mappings.retrieveAutoCompleteInfo();
- };
-
- this.saveSettings = () => {
- const prevSettings = getAutocomplete();
- const prevPolling = getPolling();
-
- this.vals = updateSettings(this.vals);
-
- // We'll only retrieve settings if polling is on.
- if (getPolling()) {
- // Find which, if any, autocomplete settings have changed.
- const settingsDiff = Object.keys(prevSettings).filter(key => prevSettings[key] !== this.vals.autocomplete[key]);
- const changedSettings = settingsDiff.reduce((changedSettingsAccum, setting) => {
- changedSettingsAccum[setting] = this.vals.autocomplete[setting];
- return changedSettingsAccum;
- }, {});
-
- const isSettingsChanged = settingsDiff.length > 0;
- const isPollingChanged = prevPolling !== getPolling();
-
- if (isSettingsChanged) {
- // If the user has changed one of the autocomplete settings, then we'll fetch just the
- // ones which have changed.
- mappings.retrieveAutoCompleteInfo(changedSettings);
- } else if (isPollingChanged) {
- // If the user has turned polling on, then we'll fetch all selected autocomplete settings.
- mappings.retrieveAutoCompleteInfo();
- }
- }
-
- $scope.kbnTopNav.close();
- };
-
- const self = this;
-
- function onEnter(event) {
- if (event.which === 13) {
- self.saveSettings();
- }
- }
-
- const boundElement = $element.bind('keydown', onEnter);
- $scope.$on('$destroy', () => boundElement.unbind('keydown', onEnter));
- },
- };
- });
diff --git a/src/legacy/core_plugins/console/public/src/directives/settings.html b/src/legacy/core_plugins/console/public/src/directives/settings.html
deleted file mode 100644
index 52e8ce77d3451..0000000000000
--- a/src/legacy/core_plugins/console/public/src/directives/settings.html
+++ /dev/null
@@ -1,213 +0,0 @@
-
-
-
diff --git a/src/legacy/core_plugins/console/public/src/directives/welcome.html b/src/legacy/core_plugins/console/public/src/directives/welcome.html
deleted file mode 100644
index 29fac7592f2f0..0000000000000
--- a/src/legacy/core_plugins/console/public/src/directives/welcome.html
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/legacy/core_plugins/console/public/src/controllers/sense_top_nav_controller.js b/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts
similarity index 63%
rename from src/legacy/core_plugins/console/public/src/controllers/sense_top_nav_controller.js
rename to src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts
index e3c1a1f1c80e4..4b9b598da8d4f 100644
--- a/src/legacy/core_plugins/console/public/src/controllers/sense_top_nav_controller.js
+++ b/src/legacy/core_plugins/console/public/src/helpers/get_top_nav.ts
@@ -17,61 +17,57 @@
* under the License.
*/
-import { KbnTopNavControllerProvider } from 'ui/kbn_top_nav/kbn_top_nav_controller';
import { i18n } from '@kbn/i18n';
-import storage from '../storage';
-export function SenseTopNavController(Private) {
- const KbnTopNavController = Private(KbnTopNavControllerProvider);
+import { IScope } from 'angular';
+import { showSettingsModal } from './settings_show_modal';
- const controller = new KbnTopNavController([
- {
- key: 'welcome',
- label: i18n.translate('console.topNav.welcomeTabLabel', {
- defaultMessage: 'Welcome'
- }),
- hideButton: true,
- template: ``,
- testId: 'consoleWelcomeButton',
- },
+// help
+import { showHelpPanel } from './help_show_panel';
+
+export function getTopNavConfig($scope: IScope, toggleHistory: () => {}) {
+ return [
{
key: 'history',
label: i18n.translate('console.topNav.historyTabLabel', {
- defaultMessage: 'History'
+ defaultMessage: 'History',
}),
description: i18n.translate('console.topNav.historyTabDescription', {
defaultMessage: 'History',
}),
- template: ``,
+ run: () => {
+ toggleHistory();
+ },
testId: 'consoleHistoryButton',
},
{
key: 'settings',
label: i18n.translate('console.topNav.settingsTabLabel', {
- defaultMessage: 'Settings'
+ defaultMessage: 'Settings',
}),
description: i18n.translate('console.topNav.settingsTabDescription', {
defaultMessage: 'Settings',
}),
- template: ``,
+ run: () => {
+ showSettingsModal();
+ },
testId: 'consoleSettingsButton',
},
{
key: 'help',
label: i18n.translate('console.topNav.helpTabLabel', {
- defaultMessage: 'Help'
+ defaultMessage: 'Help',
}),
description: i18n.translate('console.topNav.helpTabDescription', {
defaultMessage: 'Help',
}),
- template: ``,
+ run: () => {
+ const hideHelpPanel = showHelpPanel();
+ $scope.$on('$destroy', () => {
+ hideHelpPanel();
+ });
+ },
testId: 'consoleHelpButton',
},
- ]);
-
- if (storage.get('version_welcome_shown') !== '@@SENSE_REVISION') {
- controller.open('welcome');
- }
-
- return controller;
+ ];
}
diff --git a/src/legacy/core_plugins/console/public/src/directives/sense_welcome.js b/src/legacy/core_plugins/console/public/src/helpers/help_show_panel.tsx
similarity index 55%
rename from src/legacy/core_plugins/console/public/src/directives/sense_welcome.js
rename to src/legacy/core_plugins/console/public/src/helpers/help_show_panel.tsx
index 4689012645308..a57fc92e17141 100644
--- a/src/legacy/core_plugins/console/public/src/directives/sense_welcome.js
+++ b/src/legacy/core_plugins/console/public/src/helpers/help_show_panel.tsx
@@ -17,26 +17,31 @@
* under the License.
*/
-require('./sense_help_example');
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { I18nContext } from 'ui/i18n';
+import { HelpPanel } from '../components/help_panel';
-import { i18n } from '@kbn/i18n';
-import template from './welcome.html';
+let isOpen = false;
-const storage = require('../storage');
+export function showHelpPanel(): () => void {
+ const onClose = () => {
+ if (!container) return;
+ ReactDOM.unmountComponentAtNode(container);
+ isOpen = false;
+ };
-require('ui/modules')
- .get('app/sense')
- .directive('senseWelcome', function () {
- return {
- restrict: 'E',
- template,
- link: function ($scope) {
- $scope.$on('$destroy', function () {
- storage.set('version_welcome_shown', '@@SENSE_REVISION');
- });
- $scope.asWellAsFragmentText = i18n.translate('console.welcomePage.supportedRequestFormatDescription.asWellAsFragmentText', {
- defaultMessage: 'as well as'
- });
- },
- };
- });
+ const container = document.getElementById('consoleHelpPanel');
+
+ if (container && !isOpen) {
+ isOpen = true;
+ const element = (
+
+
+
+ );
+ ReactDOM.render(element, container);
+ }
+
+ return onClose;
+}
diff --git a/src/legacy/core_plugins/console/public/src/helpers/settings_show_modal.tsx b/src/legacy/core_plugins/console/public/src/helpers/settings_show_modal.tsx
new file mode 100644
index 0000000000000..a88955c0ca8bf
--- /dev/null
+++ b/src/legacy/core_plugins/console/public/src/helpers/settings_show_modal.tsx
@@ -0,0 +1,86 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { I18nContext } from 'ui/i18n';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { DevToolsSettingsModal } from '../components/settings_modal';
+import { DevToolsSettings } from '../components/dev_tools_settings';
+
+// @ts-ignore
+import mappings from '../mappings';
+// @ts-ignore
+import { getCurrentSettings, updateSettings } from '../settings';
+
+export function showSettingsModal() {
+ const container = document.getElementById('consoleSettingsModal');
+ const curSettings = getCurrentSettings();
+
+ const refreshAutocompleteSettings = () => {
+ mappings.retrieveAutoCompleteInfo();
+ };
+
+ const closeModal = () => {
+ if (!container) return;
+ ReactDOM.unmountComponentAtNode(container);
+ container.innerHTML = '';
+ };
+
+ const getAutocompleteDiff = (newSettings: DevToolsSettings, prevSettings: DevToolsSettings) => {
+ return Object.keys(newSettings.autocomplete).filter(key => {
+ // @ts-ignore
+ return prevSettings.autocomplete[key] !== newSettings.autocomplete[key];
+ });
+ };
+
+ const fetchAutocompleteSettingsIfNeeded = (
+ newSettings: DevToolsSettings,
+ prevSettings: DevToolsSettings
+ ) => {
+ // We'll only retrieve settings if polling is on.
+ const isPollingChanged = prevSettings.polling !== newSettings.polling;
+ if (newSettings.polling) {
+ const autocompleteDiff = getAutocompleteDiff(newSettings, prevSettings);
+ if (autocompleteDiff.length > 0) {
+ mappings.retrieveAutoCompleteInfo(newSettings.autocomplete);
+ } else if (isPollingChanged) {
+ mappings.retrieveAutoCompleteInfo();
+ }
+ }
+ };
+
+ const onSave = async (newSettings: DevToolsSettings) => {
+ const prevSettings = getCurrentSettings();
+ updateSettings(newSettings);
+ fetchAutocompleteSettingsIfNeeded(newSettings, prevSettings);
+ closeModal();
+ };
+
+ const element = (
+
+
+
+ );
+ ReactDOM.render(element, container);
+}
diff --git a/src/legacy/core_plugins/console/public/src/helpers/welcome_show_panel.tsx b/src/legacy/core_plugins/console/public/src/helpers/welcome_show_panel.tsx
new file mode 100644
index 0000000000000..60a66babef6e6
--- /dev/null
+++ b/src/legacy/core_plugins/console/public/src/helpers/welcome_show_panel.tsx
@@ -0,0 +1,53 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { I18nContext } from 'ui/i18n';
+import { WelcomePanel } from '../components/welcome_panel';
+// @ts-ignore
+import storage from '../storage';
+
+let isOpen = false;
+
+export function showWelcomePanel(): () => void {
+ const onClose = () => {
+ if (!container) return;
+ ReactDOM.unmountComponentAtNode(container);
+ isOpen = false;
+ };
+
+ const onDismiss = () => {
+ storage.set('version_welcome_shown', '@@SENSE_REVISION');
+ onClose();
+ };
+
+ const container = document.getElementById('consoleWelcomePanel');
+ if (container && !isOpen) {
+ isOpen = true;
+ const element = (
+
+
+
+ );
+ ReactDOM.render(element, container);
+ }
+
+ return onClose;
+}
diff --git a/src/legacy/core_plugins/console/public/src/input.js b/src/legacy/core_plugins/console/public/src/input.js
index 36a6c52fd17b8..86c2efe3a70bd 100644
--- a/src/legacy/core_plugins/console/public/src/input.js
+++ b/src/legacy/core_plugins/console/public/src/input.js
@@ -72,7 +72,7 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output, openDocu
let CURRENT_REQ_ID = 0;
- function sendCurrentRequestToES() {
+ function sendCurrentRequestToES(addedToHistoryCb) {
const reqId = ++CURRENT_REQ_ID;
@@ -139,6 +139,9 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output, openDocu
// we have someone on the other side. Add to history
history.addToHistory(esPath, esMethod, esData);
+ if (addedToHistoryCb) {
+ addedToHistoryCb();
+ }
let value = xhr.responseText;
const mode = modeForContentType(xhr.getAllResponseHeaders('Content-Type') || '');
@@ -212,7 +215,7 @@ export function initializeInput($el, $actionsEl, $copyAsCurlEl, output, openDocu
input.commands.addCommand({
name: 'send to elasticsearch',
bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter' },
- exec: sendCurrentRequestToES
+ exec: () => sendCurrentRequestToES()
});
input.commands.addCommand({
name: 'open documentation',
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index f6aa28caf0825..e815b26f4b16c 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -741,7 +741,6 @@
"console.topNav.historyTabLabel": "履歴",
"console.topNav.settingsTabDescription": "設定",
"console.topNav.settingsTabLabel": "設定",
- "console.topNav.welcomeTabLabel": "ようこそ",
"console.welcomePage.closeButtonLabel": "始めましょう",
"console.welcomePage.pageTitle": "コンソールへようこそ",
"console.welcomePage.quickIntroDescription": "コンソール UI は、エディターペイン (左) と応答ペイン (右) の 2 つのペインに分かれています。エディターでリクエストを入力し、Elasticsearch に送信します。結果が右側の応答ペインに表示されます。",
@@ -752,8 +751,6 @@
"console.welcomePage.quickTips.submitRequestDescription": "緑の三角形のボタンをクリックして ES にリクエストを送信します。",
"console.welcomePage.quickTips.useWrenchMenuDescription": "レンチメニューで他の便利な機能が使えます。",
"console.welcomePage.quickTipsTitle": "今のうちにいくつか簡単なコツをお教えします",
- "console.welcomePage.supportedRequestFormatDescription": "リクエストの入力中、コンソールが候補を提案するので、Enter/Tab を押して確定できます。これらの候補はリクエストの構造{asWellAs}インデックス、タイプに基づくものです。",
- "console.welcomePage.supportedRequestFormatDescription.asWellAsFragmentText": "や",
"console.welcomePage.supportedRequestFormatTitle": "コンソールは cURL と同様に、コンパクトなフォーマットのリクエストを理解できます。",
"core.chrome.legacyBrowserWarning": "ご使用のブラウザが Kibana のセキュリティ要件を満たしていません。",
"core.euiBasicTable.selectAllRows": "すべての行を選択",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 221a38ae918bc..1d8a88e9242ac 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -747,7 +747,6 @@
"console.topNav.historyTabLabel": "历史记录",
"console.topNav.settingsTabDescription": "设置",
"console.topNav.settingsTabLabel": "设置",
- "console.topNav.welcomeTabLabel": "欢迎",
"console.welcomePage.closeButtonLabel": "开始工作",
"console.welcomePage.pageTitle": "欢迎使用 Console",
"console.welcomePage.quickIntroDescription": "Console UI 分成两个窗格:编辑器窗格(左)和响应窗格(右)。使用编辑器键入请求并将它们提交到 Elasticsearch。结果将显示在右侧的响应窗格中。",
@@ -758,8 +757,6 @@
"console.welcomePage.quickTips.submitRequestDescription": "使用绿色三角按钮将请求提交到 ES。",
"console.welcomePage.quickTips.useWrenchMenuDescription": "使用扳手菜单执行其他有用的操作。",
"console.welcomePage.quickTipsTitle": "有几个需要您注意的有用提示",
- "console.welcomePage.supportedRequestFormatDescription": "键入请求时,Console 将提供建议,您可以通过按 Enter/Tab 键来接受建议。这些建议基于请求结构{asWellAs}您的索引和类型做出。",
- "console.welcomePage.supportedRequestFormatDescription.asWellAsFragmentText": "以及",
"console.welcomePage.supportedRequestFormatTitle": "Console 理解紧凑格式的请求,类似于 cURL:",
"core.chrome.legacyBrowserWarning": "您的浏览器不满足 Kibana 的安全要求。",
"core.euiBasicTable.selectAllRows": "选择所有行",