mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* Sense settings modal * Deleted comments * DevTools help flyout * Settings UI improvements * Improve file naming * Rename helpShowPanel * Added TS to help * React welcome flyout + removed it from top nav * Move history tool outside of top nav Improve it's behavior - now it will update when open, when a query is run. * ts fix * Code review fixes * Code review fixes * Fixed translations * Code review changes - autoclose panels * deleted unused useEffect * fix z-order of components * type check fixes * Final code review fixes
This commit is contained in:
parent
6d903c0d71
commit
4a2f36745c
24 changed files with 827 additions and 584 deletions
|
@ -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');
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<kbn-top-nav name="console" config="topNavMenu"></kbn-top-nav>
|
||||
<kbn-dev-tools-app data-test-subj="console" top-nav-config="topNavController">
|
||||
<sense-history ng-show="showHistory" is-shown="showHistory" history-dirty="lastRequestTimestamp"></sense-history>
|
||||
<div class="conApp">
|
||||
<div class="conApp__editor">
|
||||
<ul class="conApp__autoComplete" id="autocomplete"></ul>
|
||||
|
@ -32,3 +34,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</kbn-dev-tools-app>
|
||||
<div id="consoleWelcomePanel"></div>
|
||||
<div id="consoleHelpPanel"></div>
|
||||
<div id="consoleSettingsModal"></div>
|
|
@ -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;
|
||||
}
|
|
@ -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 <div id={elemId} className="conHelp__example" />;
|
||||
}
|
|
@ -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 (
|
||||
<EuiFlyout onClose={props.onClose} data-test-subj="helpFlyout" size="s">
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2>
|
||||
<FormattedMessage id="console.helpPage.pageTitle" defaultMessage="Help" />
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<EuiText>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
defaultMessage="Request format"
|
||||
id="console.helpPage.requestFormatTitle"
|
||||
/>
|
||||
</h3>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.requestFormatDescription"
|
||||
defaultMessage="You can type one or more requests in the white editor. Console understands requests in a compact format:"
|
||||
/>
|
||||
</p>
|
||||
<EditorExample panel="help" />
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommandsTitle"
|
||||
defaultMessage="Keyboard commands"
|
||||
/>
|
||||
</h3>
|
||||
<EuiSpacer />
|
||||
<dl>
|
||||
<dt>Ctrl/Cmd + I</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.autoIndentDescription"
|
||||
defaultMessage="Auto indent current request"
|
||||
/>
|
||||
</dd>
|
||||
<dt>Ctrl/Cmd + /</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.openDocumentationDescription"
|
||||
defaultMessage="Open documentation for current request"
|
||||
/>
|
||||
</dd>
|
||||
<dt>Ctrl + Space</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.openAutoCompleteDescription"
|
||||
defaultMessage="Open Auto complete (even if not typing)"
|
||||
/>
|
||||
</dd>
|
||||
<dt>Ctrl/Cmd + Enter</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.submitRequestDescription"
|
||||
defaultMessage="Submit request"
|
||||
/>
|
||||
</dd>
|
||||
<dt>Ctrl/Cmd + Up/Down</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.jumpToPreviousNextRequestDescription"
|
||||
defaultMessage="Jump to the previous/next request start or end."
|
||||
/>
|
||||
</dd>
|
||||
<dt>Ctrl/Cmd + Alt + L</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.collapseExpandCurrentScopeDescription"
|
||||
defaultMessage="Collapse/expand current scope."
|
||||
/>
|
||||
</dd>
|
||||
<dt>Ctrl/Cmd + Option + 0</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.collapseAllScopesDescription"
|
||||
defaultMessage="Collapse all scopes but the current one. Expand by adding a shift."
|
||||
/>
|
||||
</dd>
|
||||
<dt>Down arrow</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.switchFocusToAutoCompleteMenuDescription"
|
||||
defaultMessage="Switch focus to auto-complete menu. Use arrows to further select a term"
|
||||
/>
|
||||
</dd>
|
||||
<dt>Enter/Tab</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.selectCurrentlySelectedInAutoCompleteMenuDescription"
|
||||
defaultMessage="Select the currently selected or the top most term in auto-complete menu"
|
||||
/>
|
||||
</dd>
|
||||
<dt>Esc</dt>
|
||||
<dd>
|
||||
<FormattedMessage
|
||||
id="console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription"
|
||||
defaultMessage="Close auto-complete menu"
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
</EuiText>
|
||||
</EuiFlyoutBody>
|
||||
</EuiFlyout>
|
||||
);
|
||||
}
|
|
@ -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<void>;
|
||||
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 (
|
||||
<EuiOverlayMask>
|
||||
<EuiModal data-test-subj="devToolsSettingsModal" onClose={props.onClose}>
|
||||
<EuiModalHeader>
|
||||
<EuiModalHeaderTitle>
|
||||
<FormattedMessage
|
||||
id="console.settingsPage.pageTitle"
|
||||
defaultMessage="Console Settings"
|
||||
/>
|
||||
</EuiModalHeaderTitle>
|
||||
</EuiModalHeader>
|
||||
|
||||
<EuiModalBody>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="console.settingsPage.fontSizeLabel"
|
||||
defaultMessage="Font Size"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
autoFocus
|
||||
data-test-subj="setting-font-size-input"
|
||||
value={fontSize}
|
||||
min={6}
|
||||
max={50}
|
||||
onChange={e => {
|
||||
const val = parseInt(e.target.value, 10);
|
||||
if (!val) return;
|
||||
setFontSize(val);
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
checked={wrapMode}
|
||||
data-test-subj="settingsWrapLines"
|
||||
id="wrapLines"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Wrap long lines"
|
||||
id="console.settingsPage.wrapLongLinesLabelText"
|
||||
/>
|
||||
}
|
||||
onChange={e => setWrapMode(e.target.checked)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="console.settingsPage.jsonSyntaxLabel"
|
||||
defaultMessage="JSON syntax"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiSwitch
|
||||
checked={tripleQuotes}
|
||||
data-test-subj="tripleQuotes"
|
||||
id="tripleQuotes"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Use triple quotes in output pane"
|
||||
id="console.settingsPage.tripleQuotesMessage"
|
||||
/>
|
||||
}
|
||||
onChange={e => setTripleQuotes(e.target.checked)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
labelType="legend"
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="console.settingsPage.autocompleteLabel"
|
||||
defaultMessage="Autocomplete"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiCheckboxGroup
|
||||
options={autoCompleteCheckboxes}
|
||||
idToSelectedMap={checkboxIdToSelectedMap}
|
||||
onChange={(e: any) => {
|
||||
onAutocompleteChange(e as AutocompleteOptions);
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="console.settingsPage.refreshingDataLabel"
|
||||
defaultMessage="Refreshing autocomplete suggestions"
|
||||
/>
|
||||
}
|
||||
helpText={
|
||||
<FormattedMessage
|
||||
id="console.settingsPage.refreshingDataDescription"
|
||||
defaultMessage="Console refreshes autocomplete suggestions by querying Elasticsearch.
|
||||
Automatic refreshes may be an issue if you have a large cluster or if you have network limitations."
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiSwitch
|
||||
checked={polling}
|
||||
data-test-subj="autocompletePolling"
|
||||
id="autocompletePolling"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Automatically refresh autocomplete suggestions"
|
||||
id="console.settingsPage.pollingLabelText"
|
||||
/>
|
||||
}
|
||||
onChange={e => setPolling(e.target.checked)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiButton
|
||||
data-test-subj="autocompletePolling"
|
||||
id="autocompletePolling"
|
||||
onClick={props.refreshAutocompleteSettings}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Refresh autocomplete suggestions"
|
||||
id="console.settingsPage.refreshButtonLabel"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiModalBody>
|
||||
|
||||
<EuiModalFooter>
|
||||
<EuiButtonEmpty data-test-subj="settingsCancelButton" onClick={props.onClose}>
|
||||
<FormattedMessage id="console.settingsPage.cancelButtonLabel" defaultMessage="Cancel" />
|
||||
</EuiButtonEmpty>
|
||||
|
||||
<EuiButton fill data-test-subj="settings-save-button" onClick={saveSettings}>
|
||||
<FormattedMessage id="console.settingsPage.saveButtonLabel" defaultMessage="Save" />
|
||||
</EuiButton>
|
||||
</EuiModalFooter>
|
||||
</EuiModal>
|
||||
</EuiOverlayMask>
|
||||
);
|
||||
}
|
|
@ -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 (
|
||||
<EuiFlyout onClose={props.onDismiss} data-test-subj="welcomePanel" size="s">
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.pageTitle"
|
||||
defaultMessage="Welcome to Console"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<EuiText>
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickIntroTitle"
|
||||
defaultMessage="Quick intro to the UI"
|
||||
/>
|
||||
</h4>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickIntroDescription"
|
||||
defaultMessage="The Console UI is split into two panes: an editor pane (left) and a response pane (right).
|
||||
Use the editor to type requests and submit them to Elasticsearch. The results will be displayed in
|
||||
the response pane on the right side."
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.supportedRequestFormatTitle"
|
||||
defaultMessage="Console understands requests in a compact format, similar to cURL:"
|
||||
/>
|
||||
</p>
|
||||
<EditorExample panel="welcome" />
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.supportedRequestFormatDescription"
|
||||
defaultMessage="While typing a request, Console will make suggestions which you can then accept by hitting Enter/Tab.
|
||||
These suggestions are made based on the request structure as well as your indices and types."
|
||||
/>
|
||||
</p>
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickTipsTitle"
|
||||
defaultMessage="A few quick tips, while I have your attention"
|
||||
/>
|
||||
</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickTips.submitRequestDescription"
|
||||
defaultMessage="Submit requests to ES using the green triangle button."
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickTips.useWrenchMenuDescription"
|
||||
defaultMessage="Use the wrench menu for other useful things."
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickTips.cUrlFormatForRequestsDescription"
|
||||
defaultMessage="You can paste requests in cURL format and they will be translated to the Console syntax."
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickTips.resizeEditorDescription"
|
||||
defaultMessage="You can resize the editor and output panes by dragging the separator between them."
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
id="console.welcomePage.quickTips.keyboardShortcutsDescription"
|
||||
defaultMessage="Study the keyboard shortcuts under the Help button. Good stuff in there!"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</EuiText>
|
||||
</EuiFlyoutBody>
|
||||
<EuiFlyoutFooter>
|
||||
<EuiButton
|
||||
fill={true}
|
||||
fullWidth={false}
|
||||
data-test-subj="help-close-button"
|
||||
onClick={props.onDismiss}
|
||||
>
|
||||
<FormattedMessage id="console.welcomePage.closeButtonLabel" defaultMessage="Dismiss" />
|
||||
</EuiButton>
|
||||
</EuiFlyoutFooter>
|
||||
</EuiFlyout>
|
||||
);
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
sense-history {
|
||||
padding: $euiSizeS;
|
||||
}
|
||||
|
||||
.conHistory__body {
|
||||
display: flex;
|
||||
height: $euiSizeXL * 10;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
<h2
|
||||
class="euiTitle euiTitle--small"
|
||||
i18n-id="console.helpPage.pageTitle"
|
||||
i18n-default-message="Help"
|
||||
></h2>
|
||||
|
||||
<div class="euiSpacer euiSpacer--m"></div>
|
||||
|
||||
<div class="euiPanel euiPanel--paddingLarge">
|
||||
<div class="euiFlexGroup euiFlexGroup--gutterExtraLarge">
|
||||
<div class="euiFlexItem">
|
||||
<h3
|
||||
class="euiTitle euiTitle--xsmall"
|
||||
i18n-id="console.helpPage.requestFormatTitle"
|
||||
i18n-default-message="Request format"
|
||||
></h3>
|
||||
<div class="euiSpacer euiSpacer--l"></div>
|
||||
<span
|
||||
i18n-id="console.helpPage.requestFormatDescription"
|
||||
i18n-default-message="You can type one or more requests in the white editor. Console understands requests in a compact format:"
|
||||
></span>
|
||||
<sense-help-example class="conHelp__example"></sense-help-example>
|
||||
</div>
|
||||
<div class="euiFlexItem">
|
||||
<h3
|
||||
i18n-id="console.helpPage.keyboardCommandsTitle"
|
||||
i18n-default-message="Keyboard commands"
|
||||
class="euiTitle euiTitle--xsmall"
|
||||
></h3>
|
||||
<div class="euiSpacer euiSpacer--l"></div>
|
||||
<dl class="euiDescriptionList euiDescriptionList--row euiDescriptionList--compressed">
|
||||
<dt class="euiDescriptionList__title">Ctrl/Cmd + I</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.autoIndentDescription"
|
||||
i18n-default-message="Auto indent current request"
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Ctrl/Cmd + /</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.openDocumentationDescription"
|
||||
i18n-default-message="Open documentation for current request"
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Ctrl + Space</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.openAutoCompleteDescription"
|
||||
i18n-default-message="Open Auto complete (even if not typing)"
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Ctrl/Cmd + Enter</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.submitRequestDescription"
|
||||
i18n-default-message="Submit request"
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Ctrl/Cmd + Up/Down</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.jumpToPreviousNextRequestDescription"
|
||||
i18n-default-message="Jump to the previous/next request start or end."
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Ctrl/Cmd + Alt + L</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.collapseExpandCurrentScopeDescription"
|
||||
i18n-default-message="Collapse/expand current scope."
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Ctrl/Cmd + Option + 0</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.collapseAllScopesDescription"
|
||||
i18n-default-message="Collapse all scopes but the current one. Expand by adding a shift."
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Down arrow</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.switchFocusToAutoCompleteMenuDescription"
|
||||
i18n-default-message="Switch focus to auto-complete menu. Use arrows to further select a term"
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Enter/Tab</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.selectCurrentlySelectedInAutoCompleteMenuDescription"
|
||||
i18n-default-message="Select the currently selected or the top most term in auto-complete menu"
|
||||
></dd>
|
||||
<dt class="euiDescriptionList__title">Esc</dt>
|
||||
<dd
|
||||
class="euiDescriptionList__description"
|
||||
i18n-id="console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription"
|
||||
i18n-default-message="Close auto-complete menu"
|
||||
></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -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;
|
||||
|
||||
// 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})`;
|
||||
$scope.$watch('historyDirty', () => {
|
||||
this.init();
|
||||
});
|
||||
this.describeReq.cache = new WeakMap();
|
||||
|
||||
$scope.$watch('isShown', () => {
|
||||
if ($scope.isShown) this.init();
|
||||
});
|
||||
|
||||
this.init = () => {
|
||||
this.reqs = history.getHistory();
|
||||
this.selectedIndex = 0;
|
||||
this.selectedReq = this.reqs[this.selectedIndex];
|
||||
this.viewingReq = this.selectedReq;
|
||||
|
||||
// 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) => {
|
||||
|
|
|
@ -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));
|
||||
},
|
||||
};
|
||||
});
|
|
@ -1,213 +0,0 @@
|
|||
<h2
|
||||
class="kuiLocalDropdownTitle"
|
||||
i18n-id="console.settingsPage.pageTitle"
|
||||
i18n-default-message="Settings"
|
||||
></h2>
|
||||
|
||||
<form class="form" name="settingsForm" ng-submit="settingsForm.$valid && settings.saveSettings()">
|
||||
<fieldset
|
||||
class="kuiVerticalRhythm"
|
||||
role="group"
|
||||
>
|
||||
<div class="kuiLocalDropdownHeader">
|
||||
<legend
|
||||
id="consoleFontSize"
|
||||
class="kuiLocalDropdownHeader__label"
|
||||
i18n-id="console.settingsPage.fontSizeLabel"
|
||||
i18n-default-message="Font size"
|
||||
></legend>
|
||||
</div>
|
||||
|
||||
<input
|
||||
input-focus
|
||||
ng-model="settings.vals.fontSize"
|
||||
name="fontSize"
|
||||
type="number"
|
||||
required
|
||||
class="kuiLocalDropdownInput kuiVerticalRhythmSmall"
|
||||
aria-labelledby="consoleFontSize"
|
||||
data-test-subj="setting-font-size-input"
|
||||
>
|
||||
|
||||
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
|
||||
<input
|
||||
class="kuiCheckBox"
|
||||
type="checkbox"
|
||||
ng-model="settings.vals.wrapMode"
|
||||
aria-describedby="consoleFontSize"
|
||||
>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="console.settingsPage.wrapLongLinesLabelText"
|
||||
i18n-default-message="Wrap long lines"
|
||||
></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
class="kuiVerticalRhythm"
|
||||
role="group"
|
||||
>
|
||||
<div class="kuiLocalDropdownHeader">
|
||||
<legend
|
||||
class="kuiLocalDropdownHeader__label"
|
||||
i18n-id="console.settingsPage.jsonLabel"
|
||||
i18n-default-message="JSON syntax"
|
||||
></legend>
|
||||
</div>
|
||||
|
||||
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
|
||||
<input
|
||||
class="kuiCheckBox"
|
||||
name="jsonTripleQuotes"
|
||||
type="checkbox"
|
||||
ng-model="settings.vals.tripleQuotes"
|
||||
>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="console.settingsPage.tripleQuotesLabelText"
|
||||
i18n-default-message="Use triple quotes in output pane"
|
||||
></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
class="kuiVerticalRhythm"
|
||||
role="group"
|
||||
>
|
||||
<div class="kuiLocalDropdownHeader">
|
||||
<legend
|
||||
id="consoleAutocomplete"
|
||||
class="kuiLocalDropdownHeader__label"
|
||||
i18n-id="console.settingsPage.autocompleteLabel"
|
||||
i18n-default-message="Autocomplete"
|
||||
></legend>
|
||||
</div>
|
||||
|
||||
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
|
||||
<input
|
||||
class="kuiCheckBox"
|
||||
name="autocompleteFields"
|
||||
type="checkbox"
|
||||
ng-model="settings.vals.autocomplete.fields"
|
||||
aria-describedby="consoleAutocomplete"
|
||||
>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="console.settingsPage.fieldsLabelText"
|
||||
i18n-default-message="Fields"
|
||||
></span>
|
||||
</label>
|
||||
|
||||
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
|
||||
<input
|
||||
class="kuiCheckBox"
|
||||
name="autocompleteIndices"
|
||||
type="checkbox"
|
||||
ng-model="settings.vals.autocomplete.indices"
|
||||
aria-describedby="consoleAutocomplete"
|
||||
>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="console.settingsPage.indicesAndAliasesLabelText"
|
||||
i18n-default-message="Indices & Aliases"
|
||||
></span>
|
||||
</label>
|
||||
|
||||
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
|
||||
<input
|
||||
class="kuiCheckBox"
|
||||
name="autocompleteTemplates"
|
||||
type="checkbox"
|
||||
ng-model="settings.vals.autocomplete.templates"
|
||||
aria-describedby="consoleAutocomplete"
|
||||
>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="console.settingsPage.templatesLabelText"
|
||||
i18n-default-message="Templates"
|
||||
></span>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
class="kuiVerticalRhythm"
|
||||
role="group"
|
||||
ng-show="settings.isPollingVisible()"
|
||||
>
|
||||
<div class="kuiLocalDropdownHeader">
|
||||
<legend
|
||||
class="kuiLocalDropdownHeader__label"
|
||||
i18n-id="console.settingsPage.refreshingDataLabel"
|
||||
i18n-default-message="Refreshing autocomplete suggestions"
|
||||
></legend>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="kuiVerticalRhythmSmall"
|
||||
id="consoleRefreshingData"
|
||||
i18n-id="console.settingsPage.refreshingDataDescription"
|
||||
i18n-default-message="Console refreshes autocomplete suggestions by querying Elasticsearch.
|
||||
Automatic refreshes may be an issue if you have a large cluster or if you have network limitations."
|
||||
></p>
|
||||
|
||||
<label class="kuiCheckBoxLabel kuiVerticalRhythmSmall">
|
||||
<input
|
||||
class="kuiCheckBox"
|
||||
name="polling"
|
||||
type="checkbox"
|
||||
ng-model="settings.vals.polling"
|
||||
aria-describedby="consoleRefreshingData"
|
||||
>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="console.settingsPage.pollingLabelText"
|
||||
i18n-default-message="Automatically refresh autocomplete suggestions"
|
||||
></span>
|
||||
</label>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
ng-click="settings.refresh()"
|
||||
class="euiButton euiButton--primary kuiVerticalRhythmSmall"
|
||||
>
|
||||
<span class="euiButton__content">
|
||||
<span
|
||||
class="euiButton__text"
|
||||
i18n-id="console.settingsPage.refreshButtonLabel"
|
||||
i18n-default-message="Refresh autocomplete suggestions"
|
||||
></span>
|
||||
</span>
|
||||
</button>
|
||||
</fieldset>
|
||||
|
||||
<div class="kuiVerticalRhythm">
|
||||
<button
|
||||
ng-click="kbnTopNav.close()"
|
||||
class="euiButton euiButton--primary"
|
||||
>
|
||||
<span class="euiButton__content">
|
||||
<span
|
||||
class="euiButton__text"
|
||||
i18n-id="console.settingsPage.cancelButtonLabel"
|
||||
i18n-default-message="Cancel"
|
||||
></span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
ng-disabled="settingsForm.$invalid"
|
||||
class="euiButton euiButton--primary euiButton--fill"
|
||||
data-test-subj="settings-save-button"
|
||||
>
|
||||
<span class="euiButton__content">
|
||||
<span
|
||||
class="euiButton__text"
|
||||
i18n-id="console.settingsPage.saveButtonLabel"
|
||||
i18n-default-message="Save"
|
||||
></span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
|
@ -1,76 +0,0 @@
|
|||
<div class="euiText">
|
||||
|
||||
<h2
|
||||
i18n-id="console.welcomePage.pageTitle"
|
||||
i18n-default-message="Welcome to Console"
|
||||
></h2>
|
||||
|
||||
<p>
|
||||
<strong
|
||||
i18n-id="console.welcomePage.quickIntroTitle"
|
||||
i18n-default-message="Quick intro to the UI"
|
||||
></strong>
|
||||
</p>
|
||||
|
||||
<p
|
||||
i18n-id="console.welcomePage.quickIntroDescription"
|
||||
i18n-default-message="The Console UI is split into two panes: an editor pane (left) and a response pane (right).
|
||||
Use the editor to type requests and submit them to Elasticsearch. The results will be displayed in
|
||||
the response pane on the right side."
|
||||
></p>
|
||||
|
||||
<p
|
||||
i18n-id="console.welcomePage.supportedRequestFormatTitle"
|
||||
i18n-default-message="Console understands requests in a compact format, similar to cURL:"
|
||||
></p>
|
||||
<sense-help-example></sense-help-example>
|
||||
|
||||
<p
|
||||
i18n-id="console.welcomePage.supportedRequestFormatDescription"
|
||||
i18n-default-message="While typing a request, Console will make suggestions which you can then accept by hitting Enter/Tab.
|
||||
These suggestions are made based on the request structure {asWellAs} your indices and types."
|
||||
i18n-values="{ html_asWellAs: '<i>' + asWellAsFragmentText + '</i>' }"
|
||||
>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong
|
||||
i18n-id="console.welcomePage.quickTipsTitle"
|
||||
i18n-default-message="A few quick tips, while I have your attention"
|
||||
>
|
||||
</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li
|
||||
i18n-id="console.welcomePage.quickTips.submitRequestDescription"
|
||||
i18n-default-message="Submit requests to ES using the green triangle button."
|
||||
></li>
|
||||
<li
|
||||
i18n-id="console.welcomePage.quickTips.useWrenchMenuDescription"
|
||||
i18n-default-message="Use the wrench menu for other useful things."
|
||||
></li>
|
||||
<li
|
||||
i18n-id="console.welcomePage.quickTips.cUrlFormatForRequestsDescription"
|
||||
i18n-default-message="You can paste requests in cURL format and they will be translated to the Console syntax."
|
||||
></li>
|
||||
<li
|
||||
i18n-id="console.welcomePage.quickTips.resizeEditorDescription"
|
||||
i18n-default-message="You can resize the editor and output panes by dragging the separator between them."
|
||||
></li>
|
||||
<li
|
||||
i18n-id="console.welcomePage.quickTips.keyboardShortcutsDescription"
|
||||
i18n-default-message="Study the keyboard shortcuts under the Help button. Good stuff in there!"
|
||||
></li>
|
||||
</ul>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="kuiButton kuiButton--primary"
|
||||
data-test-subj="help-close-button"
|
||||
ng-click="kbnTopNav.close()"
|
||||
i18n-id="console.welcomePage.closeButtonLabel"
|
||||
i18n-default-message="Get to work"
|
||||
>
|
||||
</button>
|
||||
|
||||
</div>
|
|
@ -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: `<sense-welcome></sense-welcome>`,
|
||||
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: `<sense-history></sense-history>`,
|
||||
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: `<sense-settings></sense-settings>`,
|
||||
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: `<sense-help></sense-help>`,
|
||||
run: () => {
|
||||
const hideHelpPanel = showHelpPanel();
|
||||
$scope.$on('$destroy', () => {
|
||||
hideHelpPanel();
|
||||
});
|
||||
},
|
||||
testId: 'consoleHelpButton',
|
||||
},
|
||||
]);
|
||||
|
||||
if (storage.get('version_welcome_shown') !== '@@SENSE_REVISION') {
|
||||
controller.open('welcome');
|
||||
}
|
||||
|
||||
return controller;
|
||||
];
|
||||
}
|
|
@ -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 = (
|
||||
<I18nContext>
|
||||
<HelpPanel onClose={onClose} />
|
||||
</I18nContext>
|
||||
);
|
||||
ReactDOM.render(element, container);
|
||||
}
|
||||
|
||||
return onClose;
|
||||
}
|
|
@ -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 = (
|
||||
<I18nContext>
|
||||
<DevToolsSettingsModal
|
||||
settings={curSettings}
|
||||
onSaveSettings={onSave}
|
||||
onClose={closeModal}
|
||||
refreshAutocompleteSettings={refreshAutocompleteSettings}
|
||||
/>
|
||||
</I18nContext>
|
||||
);
|
||||
ReactDOM.render(element, container);
|
||||
}
|
|
@ -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 = (
|
||||
<I18nContext>
|
||||
<WelcomePanel onDismiss={onDismiss} />
|
||||
</I18nContext>
|
||||
);
|
||||
ReactDOM.render(element, container);
|
||||
}
|
||||
|
||||
return onClose;
|
||||
}
|
|
@ -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',
|
||||
|
|
|
@ -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": "すべての行を選択",
|
||||
|
|
|
@ -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": "选择所有行",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue