mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution][Admin][Responder] Allow user to hold a key down for the responder (#139674)
This commit is contained in:
parent
4fa5518ee8
commit
109fb0d534
2 changed files with 69 additions and 32 deletions
|
@ -59,6 +59,20 @@ describe('When entering data into the Console input', () => {
|
|||
expect(getUserInputText()).toEqual('cm');
|
||||
});
|
||||
|
||||
it('should repeat letters if the user holds letter key down on the keyboard', () => {
|
||||
render();
|
||||
enterCommand('{a>5/}', { inputOnly: true, useKeyboard: true });
|
||||
expect(getUserInputText()).toEqual('aaaaa');
|
||||
});
|
||||
|
||||
it('should not display command key names in the input, when command keys are used', () => {
|
||||
render();
|
||||
enterCommand('{Meta>}', { inputOnly: true, useKeyboard: true });
|
||||
expect(getUserInputText()).toEqual('');
|
||||
enterCommand('{Shift>}A{/Shift}', { inputOnly: true, useKeyboard: true });
|
||||
expect(getUserInputText()).toEqual('A');
|
||||
});
|
||||
|
||||
it('should display placeholder text when input area is blank', () => {
|
||||
render();
|
||||
|
||||
|
@ -201,6 +215,11 @@ describe('When entering data into the Console input', () => {
|
|||
expect(getRightOfCursorText()).toEqual('');
|
||||
});
|
||||
|
||||
it('should clear the input if the user holds down the delete/backspace key', () => {
|
||||
typeKeyboardKey('{backspace>7/}');
|
||||
expect(getUserInputText()).toEqual('');
|
||||
});
|
||||
|
||||
it('should move cursor to the left', () => {
|
||||
typeKeyboardKey('{ArrowLeft}');
|
||||
typeKeyboardKey('{ArrowLeft}');
|
||||
|
|
|
@ -5,7 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { FormEventHandler, KeyboardEventHandler, MutableRefObject } from 'react';
|
||||
import type {
|
||||
ClipboardEventHandler,
|
||||
FormEventHandler,
|
||||
KeyboardEventHandler,
|
||||
MutableRefObject,
|
||||
} from 'react';
|
||||
import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { pick } from 'lodash';
|
||||
import styled from 'styled-components';
|
||||
|
@ -65,12 +70,11 @@ export const KeyCapture = memo<KeyCaptureProps>(({ onCapture, focusRef, onStateC
|
|||
// We don't need the actual value that was last input in this component, because
|
||||
// `setLastInput()` is used with a function that returns the typed character.
|
||||
// This state is used like this:
|
||||
// 1. user presses a keyboard key
|
||||
// 2. `input` event is triggered - we store the letter typed
|
||||
// 3. the next event to be triggered (after `input`) that we listen for is `keyup`,
|
||||
// and when that is triggered, we take the input letter (already stored) and
|
||||
// call `onCapture()` with it and then set the lastInput state back to an empty string
|
||||
const [, setLastInput] = useState('');
|
||||
// 1. User presses a keyboard key down
|
||||
// 2. We store the key that was pressed
|
||||
// 3. When the 'keyup' event is triggered, we call `onCapture()`
|
||||
// with all of the character that were entered
|
||||
// 4. We set the last input back to an empty string
|
||||
const getTestId = useTestIdGenerator(useDataTestSubj());
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const blurInputRef = useRef<HTMLInputElement | null>(null);
|
||||
|
@ -96,15 +100,36 @@ export const KeyCapture = memo<KeyCaptureProps>(({ onCapture, focusRef, onStateC
|
|||
[onStateChange]
|
||||
);
|
||||
|
||||
const handleOnKeyUp = useCallback<KeyboardEventHandler<HTMLInputElement>>(
|
||||
const handleInputOnPaste = useCallback<ClipboardEventHandler>(
|
||||
(ev) => {
|
||||
// There is a condition (still not clear how it is actually happening) where the `Enter` key
|
||||
// event from the EuiSelectable component gets captured here by the Input. Its likely due to
|
||||
// the sequence of events between keyup, focus and the Focus trap component having the
|
||||
// `returnFocus` on by default.
|
||||
// To avoid having that key Event from actually being processed, we check for this custom
|
||||
// property on the event and skip processing it if we find it. This property is currently
|
||||
// set by the CommandInputHistory (using EuiSelectable).
|
||||
const value = ev.clipboardData.getData('text');
|
||||
ev.stopPropagation();
|
||||
|
||||
// hard-coded for use in onCapture and future keyboard functions
|
||||
const metaKey = {
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
key: 'Meta',
|
||||
keyCode: 91,
|
||||
metaKey: true,
|
||||
repeat: false,
|
||||
shiftKey: false,
|
||||
};
|
||||
|
||||
onCapture({
|
||||
value,
|
||||
eventDetails: metaKey,
|
||||
});
|
||||
},
|
||||
[onCapture]
|
||||
);
|
||||
|
||||
// 1. Determine if the key press is one that we need to store ex) letters, digits, values that we see
|
||||
// 2. If the user clicks a key we don't need to store as text, but we need to do logic with ex) backspace, delete, l/r arrows, we must call onCapture
|
||||
const handleOnKeyDown = useCallback<KeyboardEventHandler>(
|
||||
(ev) => {
|
||||
// checking to ensure that the key is not a control character
|
||||
const newValue = /^[\w\d]{2}/.test(ev.key) ? '' : ev.key;
|
||||
|
||||
// @ts-expect-error
|
||||
if (!isCapturing || ev._CONSOLE_IGNORE_KEY) {
|
||||
|
@ -119,6 +144,11 @@ export const KeyCapture = memo<KeyCaptureProps>(({ onCapture, focusRef, onStateC
|
|||
|
||||
ev.stopPropagation();
|
||||
|
||||
// allows for clipboard events to be captured via onPaste event handler
|
||||
if (ev.metaKey || ev.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const eventDetails = pick(ev, [
|
||||
'key',
|
||||
'altKey',
|
||||
|
@ -129,26 +159,14 @@ export const KeyCapture = memo<KeyCaptureProps>(({ onCapture, focusRef, onStateC
|
|||
'shiftKey',
|
||||
]);
|
||||
|
||||
setLastInput((value) => {
|
||||
onCapture({
|
||||
value,
|
||||
eventDetails,
|
||||
});
|
||||
|
||||
return '';
|
||||
onCapture({
|
||||
value: newValue,
|
||||
eventDetails,
|
||||
});
|
||||
},
|
||||
[isCapturing, onCapture]
|
||||
);
|
||||
|
||||
const handleOnInput = useCallback<FormEventHandler<HTMLInputElement>>((ev) => {
|
||||
const newValue = ev.currentTarget.value;
|
||||
|
||||
setLastInput((prevState) => {
|
||||
return `${prevState || ''}${newValue}`;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const keyCaptureFocusMethods = useMemo<KeyCaptureFocusInterface>(() => {
|
||||
return {
|
||||
focus: (force: boolean = false) => {
|
||||
|
@ -183,10 +201,10 @@ export const KeyCapture = memo<KeyCaptureProps>(({ onCapture, focusRef, onStateC
|
|||
spellCheck="false"
|
||||
value=""
|
||||
tabIndex={-1}
|
||||
onInput={handleOnInput}
|
||||
onKeyUp={handleOnKeyUp}
|
||||
onKeyDown={handleOnKeyDown}
|
||||
onBlur={handleInputOnBlur}
|
||||
onFocus={handleInputOnFocus}
|
||||
onPaste={handleInputOnPaste}
|
||||
onChange={NOOP} // this just silences Jest output warnings
|
||||
ref={inputRef}
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue