From d20a7d06b9efc3cb2cfdf3cc58f073dd3d2493dd Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 6 Feb 2020 08:47:39 +0100 Subject: [PATCH] [Console] Progress bar (#56628) * First round of UI updates - progress bar loader for in flight request - Network request status bar * Add notification about in flight request * Use nbsp; and update the EuiCode to use EuiBadge * Address PR feedback: - Clean up unused class names - Move the network request status bar to next to the nav bar with a grey line under it - Added the request in progress badge in the network request status bar - Removed logic forcing one request at a time! - Added notification for when a user is sending a request from a line with no request on it (no more 0 - None status). Also preserve the previuous request in this case * [NB] Fix for floating tools when request is past bottom of rendered text area!! This can be backported to 7.6 as it causes when a request is selected at the bottom of a large text buffer and the history viewer is opened. * Fix types * Update copy Remove unused SCSS Co-authored-by: Elastic Machine --- .../console_legacy/public/styles/_app.scss | 10 ++ .../public/application/components/index.ts | 1 + .../network_request_status_bar/index.ts | 20 +++ .../network_request_status_bar.tsx | 133 ++++++++++++++++++ .../application/containers/editor/editor.tsx | 53 ++++--- .../editor/legacy/console_editor/editor.tsx | 4 +- .../legacy/console_editor/editor_output.tsx | 21 +-- .../application/containers/main/main.tsx | 53 +++++-- .../send_request_to_es.ts | 46 ++++-- .../use_send_current_request_to_es.ts | 17 ++- .../legacy_core_editor/legacy_core_editor.ts | 31 ++-- .../public/application/stores/request.ts | 4 +- .../console/public/lib/es/{es.js => es.ts} | 20 +-- src/plugins/console/public/lib/es/index.ts | 20 +++ 14 files changed, 351 insertions(+), 82 deletions(-) create mode 100644 src/plugins/console/public/application/components/network_request_status_bar/index.ts create mode 100644 src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx rename src/plugins/console/public/lib/es/{es.js => es.ts} (76%) create mode 100644 src/plugins/console/public/lib/es/index.ts diff --git a/src/legacy/core_plugins/console_legacy/public/styles/_app.scss b/src/legacy/core_plugins/console_legacy/public/styles/_app.scss index 3b6297f9cdbff..865a4fc7fafb0 100644 --- a/src/legacy/core_plugins/console_legacy/public/styles/_app.scss +++ b/src/legacy/core_plugins/console_legacy/public/styles/_app.scss @@ -48,6 +48,7 @@ button { line-height: inherit; } + position: absolute; z-index: $euiZLevel1; top: 0; @@ -89,3 +90,12 @@ .conApp__settingsModal { min-width: 460px; } + +.conApp__requestProgressBarContainer { + position: relative; + z-index: $euiZLevel2; +} + +.conApp__tabsExtension { + border-bottom: $euiBorderThin; +} diff --git a/src/plugins/console/public/application/components/index.ts b/src/plugins/console/public/application/components/index.ts index eccde899a2640..d9a8aa9328b73 100644 --- a/src/plugins/console/public/application/components/index.ts +++ b/src/plugins/console/public/application/components/index.ts @@ -17,6 +17,7 @@ * under the License. */ +export { NetworkRequestStatusBar } from './network_request_status_bar'; export { SomethingWentWrongCallout } from './something_went_wrong_callout'; export { TopNavMenuItem, TopNavMenu } from './top_nav_menu'; export { ConsoleMenu } from './console_menu'; diff --git a/src/plugins/console/public/application/components/network_request_status_bar/index.ts b/src/plugins/console/public/application/components/network_request_status_bar/index.ts new file mode 100644 index 0000000000000..ce214c1cdfffa --- /dev/null +++ b/src/plugins/console/public/application/components/network_request_status_bar/index.ts @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export { NetworkRequestStatusBar } from './network_request_status_bar'; diff --git a/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx b/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx new file mode 100644 index 0000000000000..6915ff15f374d --- /dev/null +++ b/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx @@ -0,0 +1,133 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import React, { FunctionComponent } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiBadge, EuiText, EuiToolTip } from '@elastic/eui'; + +export interface Props { + requestInProgress: boolean; + requestResult?: { + // Status code of the request, e.g., 200 + statusCode: number; + + // Status text of the request, e.g., OK + statusText: string; + + // Method of the request, e.g., GET + method: string; + + // The path of endpoint that was called, e.g., /_search + endpoint: string; + + // The time, in milliseconds, that the last request took + timeElapsedMs: number; + }; +} + +const mapStatusCodeToBadgeColor = (statusCode: number) => { + if (statusCode <= 199) { + return 'default'; + } + + if (statusCode <= 299) { + return 'secondary'; + } + + if (statusCode <= 399) { + return 'primary'; + } + + if (statusCode <= 499) { + return 'warning'; + } + + return 'danger'; +}; + +export const NetworkRequestStatusBar: FunctionComponent = ({ + requestInProgress, + requestResult, +}) => { + let content: React.ReactNode = null; + + if (requestInProgress) { + content = ( + + + {i18n.translate('console.requestInProgressBadgeText', { + defaultMessage: 'Request in progress', + })} + + + ); + } else if (requestResult) { + const { endpoint, method, statusCode, statusText, timeElapsedMs } = requestResult; + + content = ( + <> + + {`${method} ${ + endpoint.startsWith('/') ? endpoint : '/' + endpoint + }`} + } + > + + {/* Use   to ensure that no matter the width we don't allow line breaks */} + {statusCode} - {statusText} + + + + + + {i18n.translate('console.requestTimeElapasedBadgeTooltipContent', { + defaultMessage: 'Time Elapsed', + })} + + } + > + + + {timeElapsedMs} {'ms'} + + + + + + ); + } + + return ( + + {content} + + ); +}; diff --git a/src/plugins/console/public/application/containers/editor/editor.tsx b/src/plugins/console/public/application/containers/editor/editor.tsx index 5c7fe293651fb..0bfe837f2cd90 100644 --- a/src/plugins/console/public/application/containers/editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/editor.tsx @@ -17,14 +17,15 @@ * under the License. */ -import React, { useCallback } from 'react'; +import React, { useCallback, memo } from 'react'; import { debounce } from 'lodash'; +import { EuiProgress } from '@elastic/eui'; import { EditorContentSpinner } from '../../components'; import { Panel, PanelsContainer } from '../../../../../kibana_react/public'; import { Editor as EditorUI, EditorOutput } from './legacy/console_editor'; import { StorageKeys } from '../../../services'; -import { useEditorReadContext, useServicesContext } from '../../contexts'; +import { useEditorReadContext, useServicesContext, useRequestReadContext } from '../../contexts'; const INITIAL_PANEL_WIDTH = 50; const PANEL_MIN_WIDTH = '100px'; @@ -33,12 +34,13 @@ interface Props { loading: boolean; } -export const Editor = ({ loading }: Props) => { +export const Editor = memo(({ loading }: Props) => { const { services: { storage }, } = useServicesContext(); const { currentTextObject } = useEditorReadContext(); + const { requestInFlight } = useRequestReadContext(); const [firstPanelWidth, secondPanelWidth] = storage.get(StorageKeys.WIDTH, [ INITIAL_PANEL_WIDTH, @@ -55,23 +57,30 @@ export const Editor = ({ loading }: Props) => { if (!currentTextObject) return null; return ( - - - {loading ? ( - - ) : ( - - )} - - - {loading ? : } - - + <> + {requestInFlight ? ( +
+ +
+ ) : null} + + + {loading ? ( + + ) : ( + + )} + + + {loading ? : } + + + ); -}; +}); diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx index 759e3dbafb39c..b3e966ddffa4c 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx @@ -211,14 +211,14 @@ function EditorUI({ initialTextValue }: EditorProps) {