mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Solution][Endpoint] UX adjustment and improvement for Responder (#136347)
- Remove the word "ENDPOINT" from the console's header information - Add additional spacing between the Host name and the "Last seen" information that is shown in the console's header - Change console header area to be same color as page background (white in light theme) - adjust the header area (and other primary console containers) to have 16px padding - Change input area placeholder text - increase the bottom border of the input area, when focused, to 2px (`euiBorderThick`) - adjust the footer hint test area to have 4px padding at top/bottom. - adjust padding and spacing for the command output area - change behaviour around the focusing on the input area: - it no longer auto-focuses on the input area every time the user clicks on the page. It now behaves more like how other UI interfaces work (original intent was more for when the POC was done where it was attempting to mirror a "real" CLI terminal) - The input area now also support "tab"'ing into it - The input area will continue to receive focus when Responder is initially opened
This commit is contained in:
parent
fef8e72286
commit
ec5eb448d5
24 changed files with 112 additions and 127 deletions
|
@ -95,7 +95,9 @@ export const CommandExecutionOutput = memo<CommandExecutionOutputProps>(
|
|||
<UserCommandInput input={command.input} />
|
||||
</div>
|
||||
<div>
|
||||
{/* UX desire for 12px (current theme): achieved with EuiSpace sizes - s (8px) + xs (4px) */}
|
||||
<EuiSpacer size="s" />
|
||||
<EuiSpacer size="xs" />
|
||||
|
||||
<RenderComponent
|
||||
command={command}
|
||||
|
|
|
@ -17,15 +17,15 @@ import { ConsoleText } from './console_text';
|
|||
|
||||
const COMMAND_EXECUTION_RESULT_SUCCESS_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.commandExecutionResult.successTitle',
|
||||
{ defaultMessage: 'Success. Action was complete.' }
|
||||
{ defaultMessage: 'Action completed.' }
|
||||
);
|
||||
const COMMAND_EXECUTION_RESULT_FAILURE_TITLE = i18n.translate(
|
||||
'xpack.securitySolution.commandExecutionResult.failureTitle',
|
||||
{ defaultMessage: 'Error. Action failed.' }
|
||||
{ defaultMessage: 'Action failed.' }
|
||||
);
|
||||
const COMMAND_EXECUTION_RESULT_PENDING = i18n.translate(
|
||||
'xpack.securitySolution.commandExecutionResult.pending',
|
||||
{ defaultMessage: 'Action pending' }
|
||||
{ defaultMessage: 'Action pending.' }
|
||||
);
|
||||
|
||||
export type CommandExecutionResultProps = PropsWithChildren<{
|
||||
|
|
|
@ -260,7 +260,7 @@ describe('When entering data into the Console input', () => {
|
|||
expect(getUserInputText()).toEqual('c');
|
||||
expect(getRightOfCursorText()).toEqual('md1 ');
|
||||
|
||||
expect(getFooterText()).toEqual('cmd1 ');
|
||||
expect(getFooterText()).toEqual('Hit enter to execute');
|
||||
});
|
||||
|
||||
// FIXME:PT uncomment once task OLM task #4384 is implemented
|
||||
|
|
|
@ -33,8 +33,8 @@ const CommandInputContainer = styled.div`
|
|||
}
|
||||
|
||||
&.active {
|
||||
border-bottom: solid ${({ theme: { eui } }) => eui.euiBorderWidthThin}
|
||||
${({ theme: { eui } }) => eui.euiColorPrimary};
|
||||
border-bottom: ${({ theme: { eui } }) => eui.euiBorderThick};
|
||||
border-bottom-color: ${({ theme: { eui } }) => eui.euiColorPrimary};
|
||||
}
|
||||
|
||||
.textEntered {
|
||||
|
@ -256,6 +256,12 @@ export const CommandInput = memo<CommandInputProps>(({ prompt = '', focusRef, ..
|
|||
[dispatch, rightOfCursor.text]
|
||||
);
|
||||
|
||||
const handleOnFocus = useCallback(() => {
|
||||
if (!isKeyInputBeingCaptured) {
|
||||
dispatch({ type: 'addFocusToKeyCapture' });
|
||||
}
|
||||
}, [dispatch, isKeyInputBeingCaptured]);
|
||||
|
||||
// Execute the command if one was ENTER'd.
|
||||
useEffect(() => {
|
||||
if (commandToExecute) {
|
||||
|
@ -271,6 +277,8 @@ export const CommandInput = memo<CommandInputProps>(({ prompt = '', focusRef, ..
|
|||
className={focusClassName}
|
||||
onClick={handleTypingAreaClick}
|
||||
ref={containerRef}
|
||||
tabIndex={0}
|
||||
onFocus={handleOnFocus}
|
||||
>
|
||||
<EuiFlexGroup
|
||||
wrap={true}
|
||||
|
|
|
@ -20,13 +20,9 @@ const UNKNOWN_COMMAND_HINT = (commandName: string) =>
|
|||
values: { commandName },
|
||||
});
|
||||
|
||||
const COMMAND_USAGE_HINT = (usage: string) =>
|
||||
i18n.translate('xpack.securitySolution.useInputHints.commandUsage', {
|
||||
defaultMessage: '{usage}',
|
||||
values: {
|
||||
usage,
|
||||
},
|
||||
});
|
||||
const NO_ARGUMENTS_HINT = i18n.translate('xpack.securitySolution.useInputHints.noArguments', {
|
||||
defaultMessage: 'Hit enter to execute',
|
||||
});
|
||||
|
||||
/**
|
||||
* Auto-generates console footer "hints" while user is interacting with the input area
|
||||
|
@ -48,18 +44,43 @@ export const useInputHints = () => {
|
|||
if (commandEntered && !isInputPopoverOpen) {
|
||||
// Is valid command name? ==> show usage
|
||||
if (commandEnteredDefinition) {
|
||||
const exampleInstruction = commandEnteredDefinition?.exampleInstruction ?? '';
|
||||
const exampleUsage = commandEnteredDefinition?.exampleUsage ?? '';
|
||||
|
||||
let hint = exampleInstruction ?? '';
|
||||
|
||||
if (exampleUsage) {
|
||||
if (exampleInstruction) {
|
||||
// leading space below is intentional
|
||||
hint += ` ${i18n.translate('xpack.securitySolution.useInputHints.exampleInstructions', {
|
||||
defaultMessage: 'Ex: [ {exampleUsage} ]',
|
||||
values: {
|
||||
exampleUsage,
|
||||
},
|
||||
})}`;
|
||||
} else {
|
||||
hint += exampleUsage;
|
||||
}
|
||||
}
|
||||
|
||||
// If the command did not define any hint, then generate the command useage from the definition.
|
||||
// If the command did define `exampleInstruction` but not `exampleUsage`, then generate the
|
||||
// usage from the command definition and then append it.
|
||||
//
|
||||
// Generated usage is only created if the command has arguments.
|
||||
if (!hint || !exampleUsage) {
|
||||
const commandArguments = getArgumentsForCommand(commandEnteredDefinition);
|
||||
|
||||
if (commandArguments.length > 0) {
|
||||
hint += `${commandEnteredDefinition.name} ${commandArguments}`;
|
||||
} else {
|
||||
hint += NO_ARGUMENTS_HINT;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: 'updateFooterContent',
|
||||
payload: {
|
||||
value:
|
||||
commandEnteredDefinition.exampleUsage && commandEnteredDefinition.exampleInstruction
|
||||
? `${commandEnteredDefinition.exampleInstruction} Ex: [${commandEnteredDefinition.exampleUsage}]`
|
||||
: COMMAND_USAGE_HINT(
|
||||
`${commandEnteredDefinition.name} ${getArgumentsForCommand(
|
||||
commandEnteredDefinition
|
||||
)}`
|
||||
),
|
||||
},
|
||||
payload: { value: hint },
|
||||
});
|
||||
} else {
|
||||
dispatch({
|
||||
|
|
|
@ -93,6 +93,8 @@ export const CommandList = memo<CommandListProps>(({ commands, display = 'defaul
|
|||
};
|
||||
},
|
||||
});
|
||||
|
||||
dispatch({ type: 'addFocusToKeyCapture' });
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
|
|
@ -17,7 +17,7 @@ import { PageOverlay } from '../../../../page_overlay/page_overlay';
|
|||
import { ConsoleExitModal } from './console_exit_modal';
|
||||
|
||||
const BACK_LABEL = i18n.translate('xpack.securitySolution.consolePageOverlay.backButtonLabel', {
|
||||
defaultMessage: 'Return to page content',
|
||||
defaultMessage: 'Back',
|
||||
});
|
||||
|
||||
export interface ConsolePageOverlayProps {
|
||||
|
|
|
@ -111,7 +111,7 @@ describe('When a Console command is entered by the user', () => {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(renderResult.getByTestId('test-unknownCommandError').textContent).toEqual(
|
||||
'Unsupported text/commandThe text you entered foo-foo is unsupported! Click or type help for assistance.'
|
||||
'Unsupported text/commandThe text you entered foo-foo is unsupported! Click Help or type help for assistance.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,8 +13,7 @@ import type { ConsoleDataAction, ConsoleStoreReducer } from '../types';
|
|||
export const INPUT_DEFAULT_PLACEHOLDER_TEXT = i18n.translate(
|
||||
'xpack.securitySolution.handleInputAreaState.inputPlaceholderText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Click here to type and submit an action. For assistance, use the "help" action',
|
||||
defaultMessage: 'Submit response action',
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ export const UnknownCommand = memo<CommandExecutionComponentProps>(({ command, s
|
|||
<ConsoleCodeBlock>
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.console.unknownCommand.helpMessage"
|
||||
defaultMessage="The text you entered {userInput} is unsupported! Click {helpIcon} or type {helpCmd} for assistance."
|
||||
defaultMessage="The text you entered {userInput} is unsupported! Click {helpIcon} Help or type {helpCmd} for assistance."
|
||||
values={{
|
||||
userInput: (
|
||||
<ConsoleCodeBlock bold inline>
|
||||
|
|
|
@ -34,7 +34,7 @@ describe('When using Console component', () => {
|
|||
|
||||
it('should focus on input area when it gains focus', () => {
|
||||
render();
|
||||
userEvent.click(renderResult.getByTestId('test-mainPanel'));
|
||||
userEvent.click(renderResult.getByTestId('test-mainPanel-inputArea'));
|
||||
|
||||
expect(document.activeElement!.classList.contains('invisible-input')).toBe(true);
|
||||
});
|
||||
|
|
|
@ -40,19 +40,28 @@ const ConsoleWindow = styled.div`
|
|||
|
||||
&-container {
|
||||
padding: ${({ theme: { eui } }) => eui.euiSizeL} ${({ theme: { eui } }) => eui.euiSizeL}
|
||||
${({ theme: { eui } }) => eui.euiSizeS} ${({ theme: { eui } }) => eui.euiSizeM};
|
||||
${({ theme: { eui } }) => eui.euiSizeL} ${({ theme: { eui } }) => eui.euiSizeL};
|
||||
}
|
||||
|
||||
&-header {
|
||||
background-color: ${({ theme: { eui } }) => eui.euiColorEmptyShade};
|
||||
border-bottom: 1px solid ${({ theme: { eui } }) => eui.euiColorLightShade};
|
||||
border-top-left-radius: ${({ theme: { eui } }) => eui.euiBorderRadiusSmall};
|
||||
border-top-right-radius: ${({ theme: { eui } }) => eui.euiBorderRadiusSmall};
|
||||
padding: ${({ theme: { eui } }) => eui.euiSize} ${({ theme: { eui } }) => eui.euiSize}
|
||||
${({ theme: { eui } }) => eui.euiSize} ${({ theme: { eui } }) => eui.euiSize};
|
||||
}
|
||||
|
||||
&-footer,
|
||||
&-commandInput {
|
||||
padding-top: ${({ theme: { eui } }) => eui.euiSizeXS};
|
||||
padding-bottom: ${({ theme: { eui } }) => eui.euiSizeXS};
|
||||
}
|
||||
|
||||
&-footer {
|
||||
padding-top: 0;
|
||||
padding-bottom: ${({ theme: { eui } }) => eui.euiSizeXS};
|
||||
}
|
||||
|
||||
&-rightPanel {
|
||||
width: 35%;
|
||||
background-color: ${({ theme: { eui } }) => eui.euiFormBackgroundColor};
|
||||
|
@ -138,7 +147,7 @@ export const Console = memo<ConsoleProps>(
|
|||
HelpComponent={HelpComponent}
|
||||
dataTestSubj={commonProps['data-test-subj']}
|
||||
>
|
||||
<ConsoleWindow onClick={setFocusOnInput} {...commonProps}>
|
||||
<ConsoleWindow {...commonProps}>
|
||||
<EuiFlexGroup className="layout" gutterSize="none" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup
|
||||
|
@ -148,7 +157,7 @@ export const Console = memo<ConsoleProps>(
|
|||
responsive={false}
|
||||
data-test-subj={getTestId('mainPanel')}
|
||||
>
|
||||
<EuiFlexItem grow={false} className="layout-container layout-header">
|
||||
<EuiFlexItem grow={false} className="layout-header">
|
||||
<ConsoleHeader TitleComponent={TitleComponent} />
|
||||
</EuiFlexItem>
|
||||
|
||||
|
@ -173,7 +182,12 @@ export const Console = memo<ConsoleProps>(
|
|||
<HistoryOutput />
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} className="layout-container layout-commandInput">
|
||||
<EuiFlexItem
|
||||
onClick={setFocusOnInput}
|
||||
grow={false}
|
||||
className="layout-container layout-commandInput"
|
||||
data-test-subj={getTestId('mainPanel-inputArea')}
|
||||
>
|
||||
<CommandInput prompt={prompt} focusRef={inputFocusRef} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} className="layout-container layout-footer">
|
||||
|
|
|
@ -181,7 +181,9 @@ export const getArgumentsForCommand = (command: CommandDefinition): string[] =>
|
|||
optional: optionalArgs,
|
||||
});
|
||||
})
|
||||
: [buildArgumentText({ required: requiredArgs, optional: optionalArgs })];
|
||||
: requiredArgs || optionalArgs
|
||||
? [buildArgumentText({ required: requiredArgs, optional: optionalArgs })]
|
||||
: [];
|
||||
};
|
||||
|
||||
export const parsedPidOrEntityIdParameter = (parameters: {
|
||||
|
|
|
@ -63,9 +63,18 @@ export interface CommandDefinition<TMeta = any> {
|
|||
/** If all args are optional, but at least one must be defined, set to true */
|
||||
mustHaveArgs?: boolean;
|
||||
|
||||
exampleUsage?: string;
|
||||
/**
|
||||
* Displayed in the input hint area when the user types the command. The Command usage will be
|
||||
* appended to this value
|
||||
*/
|
||||
exampleInstruction?: string;
|
||||
|
||||
/**
|
||||
* Displayed in the input hint area when the user types the command. This value will override
|
||||
* the command usage generated by the console from the Command Definition
|
||||
*/
|
||||
exampleUsage?: string;
|
||||
|
||||
/**
|
||||
* Validate the command entered by the user. This is called only after the Console has ran
|
||||
* through all of its builtin validations (based on `CommandDefinition`).
|
||||
|
|
|
@ -12,10 +12,10 @@ import type { CommandExecutionResultComponent } from '../console/components/comm
|
|||
import type { ImmutableArray } from '../../../../common/endpoint/types';
|
||||
|
||||
export const ActionError = memo<{
|
||||
title: string;
|
||||
dataTestSubj?: string;
|
||||
errors: ImmutableArray<string>;
|
||||
title?: string;
|
||||
ResultComponent: CommandExecutionResultComponent;
|
||||
dataTestSubj?: string;
|
||||
}>(({ title, dataTestSubj, errors, ResultComponent }) => {
|
||||
return (
|
||||
<ResultComponent showAs="failure" title={title} data-test-subj={dataTestSubj}>
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('Responder header endpoint info', () => {
|
|||
});
|
||||
it('should show endpoint name', async () => {
|
||||
const name = await renderResult.findByTestId('responderHeaderEndpointName');
|
||||
expect(name.textContent).toBe(`ENDPOINT ${endpointDetails.metadata.host.name}`);
|
||||
expect(name.textContent).toBe(`${endpointDetails.metadata.host.name}`);
|
||||
});
|
||||
it('should show agent and isolation status', async () => {
|
||||
const agentStatus = await renderResult.findByTestId(
|
||||
|
|
|
@ -6,7 +6,14 @@
|
|||
*/
|
||||
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiLoadingContent, EuiToolTip } from '@elastic/eui';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiText,
|
||||
EuiLoadingContent,
|
||||
EuiToolTip,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage, FormattedRelative } from '@kbn/i18n-react';
|
||||
import { useGetEndpointDetails } from '../../hooks/endpoint/use_get_endpoint_details';
|
||||
import { useGetEndpointPendingActionsSummary } from '../../hooks/endpoint/use_get_endpoint_pending_actions_summary';
|
||||
|
@ -60,13 +67,7 @@ export const HeaderEndpointInfo = memo<HeaderEndpointInfoProps>(({ endpointId })
|
|||
anchorClassName="eui-textTruncate"
|
||||
>
|
||||
<EuiText size="s" data-test-subj="responderHeaderEndpointName">
|
||||
<h6 className="eui-textTruncate">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.responder.header.endpointName"
|
||||
defaultMessage="ENDPOINT {name}"
|
||||
values={{ name: endpointDetails.metadata.host.name }}
|
||||
/>
|
||||
</h6>
|
||||
<h6 className="eui-textTruncate">{endpointDetails.metadata.host.name}</h6>
|
||||
</EuiText>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
|
@ -81,6 +82,7 @@ export const HeaderEndpointInfo = memo<HeaderEndpointInfoProps>(({ endpointId })
|
|||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText color="subdued" size="s" data-test-subj="responderHeaderLastSeen">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.responder.header.lastSeen"
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import React, { memo, useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { ActionDetails } from '../../../../common/endpoint/types';
|
||||
import { useGetActionDetails } from '../../hooks/endpoint/use_get_action_details';
|
||||
import type { EndpointCommandDefinitionMeta } from './types';
|
||||
|
@ -81,10 +80,6 @@ export const IsolateActionResult = memo<
|
|||
if (completedActionDetails?.errors) {
|
||||
return (
|
||||
<ActionError
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.isolate.errorMessageTitle',
|
||||
{ defaultMessage: 'Error. Isolate action failed.' }
|
||||
)}
|
||||
dataTestSubj={'isolateErrorCallout'}
|
||||
errors={completedActionDetails?.errors}
|
||||
ResultComponent={ResultComponent}
|
||||
|
@ -93,14 +88,6 @@ export const IsolateActionResult = memo<
|
|||
}
|
||||
|
||||
// Show Success
|
||||
return (
|
||||
<ResultComponent
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.isolate.successMessageTitle',
|
||||
{ defaultMessage: 'Success. Host isolated.' }
|
||||
)}
|
||||
data-test-subj="isolateSuccessCallout"
|
||||
/>
|
||||
);
|
||||
return <ResultComponent showAs="success" data-test-subj="isolateSuccessCallout" />;
|
||||
});
|
||||
IsolateActionResult.displayName = 'IsolateActionResult';
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
|
||||
import React, { memo, useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import type { ActionDetails } from '../../../../common/endpoint/types';
|
||||
import { useGetActionDetails } from '../../hooks/endpoint/use_get_action_details';
|
||||
import type { EndpointCommandDefinitionMeta } from './types';
|
||||
|
@ -84,24 +82,13 @@ export const KillProcessActionResult = memo<
|
|||
|
||||
// Show nothing if still pending
|
||||
if (isPending) {
|
||||
return (
|
||||
<ResultComponent showAs="pending">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpointResponseActions.killProcess.pendingMessage"
|
||||
defaultMessage="Killing process"
|
||||
/>
|
||||
</ResultComponent>
|
||||
);
|
||||
return <ResultComponent showAs="pending" />;
|
||||
}
|
||||
|
||||
// Show errors
|
||||
if (completedActionDetails?.errors) {
|
||||
return (
|
||||
<ActionError
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.killProcess.errorMessageTitle',
|
||||
{ defaultMessage: 'Kill process action failure' }
|
||||
)}
|
||||
dataTestSubj={'killProcessErrorCallout'}
|
||||
errors={completedActionDetails?.errors}
|
||||
ResultComponent={ResultComponent}
|
||||
|
@ -110,14 +97,6 @@ export const KillProcessActionResult = memo<
|
|||
}
|
||||
|
||||
// Show Success
|
||||
return (
|
||||
<ResultComponent
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.killProcess.successMessageTitle',
|
||||
{ defaultMessage: 'Process killed successfully!' }
|
||||
)}
|
||||
data-test-subj="killProcessSuccessCallout"
|
||||
/>
|
||||
);
|
||||
return <ResultComponent showAs="success" data-test-subj="killProcessSuccessCallout" />;
|
||||
});
|
||||
KillProcessActionResult.displayName = 'KillProcessActionResult';
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import React, { memo, useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { ActionDetails } from '../../../../common/endpoint/types';
|
||||
import { useGetActionDetails } from '../../hooks/endpoint/use_get_action_details';
|
||||
import type { EndpointCommandDefinitionMeta } from './types';
|
||||
|
@ -81,10 +80,6 @@ export const ReleaseActionResult = memo<
|
|||
if (completedActionDetails?.errors) {
|
||||
return (
|
||||
<ActionError
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.release.errorMessageTitle',
|
||||
{ defaultMessage: 'Error. Release action failed.' }
|
||||
)}
|
||||
dataTestSubj={'releaseErrorCallout'}
|
||||
errors={completedActionDetails?.errors}
|
||||
ResultComponent={ResultComponent}
|
||||
|
@ -93,14 +88,6 @@ export const ReleaseActionResult = memo<
|
|||
}
|
||||
|
||||
// Show Success
|
||||
return (
|
||||
<ResultComponent
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.release.successMessageTitle',
|
||||
{ defaultMessage: 'Success. Host released.' }
|
||||
)}
|
||||
data-test-subj="releaseSuccessCallout"
|
||||
/>
|
||||
);
|
||||
return <ResultComponent data-test-subj="releaseSuccessCallout" />;
|
||||
});
|
||||
ReleaseActionResult.displayName = 'ReleaseActionResult';
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
|
||||
import React, { memo, useEffect } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import type { ActionDetails } from '../../../../common/endpoint/types';
|
||||
import { useGetActionDetails } from '../../hooks/endpoint/use_get_action_details';
|
||||
import type { EndpointCommandDefinitionMeta } from './types';
|
||||
|
@ -78,24 +76,13 @@ export const SuspendProcessActionResult = memo<
|
|||
|
||||
// Show nothing if still pending
|
||||
if (isPending) {
|
||||
return (
|
||||
<ResultComponent showAs="pending">
|
||||
<FormattedMessage
|
||||
id="xpack.securitySolution.endpointResponseActions.suspendProcess.pendingMessage"
|
||||
defaultMessage="Suspending process"
|
||||
/>
|
||||
</ResultComponent>
|
||||
);
|
||||
return <ResultComponent showAs="pending" />;
|
||||
}
|
||||
|
||||
// Show errors
|
||||
if (completedActionDetails?.errors) {
|
||||
return (
|
||||
<ActionError
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.suspendProcess.errorMessageTitle',
|
||||
{ defaultMessage: 'Suspend process action failure' }
|
||||
)}
|
||||
dataTestSubj={'suspendProcessErrorCallout'}
|
||||
errors={completedActionDetails?.errors}
|
||||
ResultComponent={ResultComponent}
|
||||
|
@ -104,14 +91,6 @@ export const SuspendProcessActionResult = memo<
|
|||
}
|
||||
|
||||
// Show Success
|
||||
return (
|
||||
<ResultComponent
|
||||
title={i18n.translate(
|
||||
'xpack.securitySolution.endpointResponseActions.suspendProcess.successMessageTitle',
|
||||
{ defaultMessage: 'Process suspended successfully' }
|
||||
)}
|
||||
data-test-subj="suspendProcessSuccessCallout"
|
||||
/>
|
||||
);
|
||||
return <ResultComponent data-test-subj="suspendProcessSuccessCallout" />;
|
||||
});
|
||||
SuspendProcessActionResult.displayName = 'SuspendProcessActionResult';
|
||||
|
|
|
@ -26444,8 +26444,6 @@
|
|||
"xpack.securitySolution.endpointManagemnet.noPermissionsText": "Vous ne disposez pas des autorisations Kibana requises pour utiliser Elastic Security Administration",
|
||||
"xpack.securitySolution.endpointPolicyStatus.revisionNumber": "rév. {revNumber}",
|
||||
"xpack.securitySolution.endpointPolicyStatus.tooltipTitleLabel": "Politique appliquée",
|
||||
"xpack.securitySolution.endpointResponseActions.isolate.errorMessageTitle": "Échec",
|
||||
"xpack.securitySolution.endpointResponseActions.isolate.successMessageTitle": "Réussite",
|
||||
"xpack.securitySolution.endpointResponseActions.status.agentStatus": "Statut de l'agent",
|
||||
"xpack.securitySolution.endpointResponseActions.status.lastActive": "Dernière activité",
|
||||
"xpack.securitySolution.endpointResponseActions.status.policyStatus": "Statut de la politique",
|
||||
|
|
|
@ -26429,8 +26429,6 @@
|
|||
"xpack.securitySolution.endpointManagemnet.noPermissionsText": "Elastic Security Administrationを使用するために必要なKibana権限がありません。",
|
||||
"xpack.securitySolution.endpointPolicyStatus.revisionNumber": "rev. {revNumber}",
|
||||
"xpack.securitySolution.endpointPolicyStatus.tooltipTitleLabel": "ポリシーが適用されました",
|
||||
"xpack.securitySolution.endpointResponseActions.isolate.errorMessageTitle": "失敗",
|
||||
"xpack.securitySolution.endpointResponseActions.isolate.successMessageTitle": "成功",
|
||||
"xpack.securitySolution.endpointResponseActions.status.agentStatus": "エージェントステータス",
|
||||
"xpack.securitySolution.endpointResponseActions.status.lastActive": "前回のアーカイブ",
|
||||
"xpack.securitySolution.endpointResponseActions.status.policyStatus": "ポリシーステータス",
|
||||
|
|
|
@ -26456,8 +26456,6 @@
|
|||
"xpack.securitySolution.endpointManagemnet.noPermissionsText": "您没有所需的 Kibana 权限,无法使用 Elastic Security 管理",
|
||||
"xpack.securitySolution.endpointPolicyStatus.revisionNumber": "修订版 {revNumber}",
|
||||
"xpack.securitySolution.endpointPolicyStatus.tooltipTitleLabel": "已应用策略",
|
||||
"xpack.securitySolution.endpointResponseActions.isolate.errorMessageTitle": "失败",
|
||||
"xpack.securitySolution.endpointResponseActions.isolate.successMessageTitle": "成功",
|
||||
"xpack.securitySolution.endpointResponseActions.status.agentStatus": "代理状态",
|
||||
"xpack.securitySolution.endpointResponseActions.status.lastActive": "上次活动时间",
|
||||
"xpack.securitySolution.endpointResponseActions.status.policyStatus": "策略状态",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue