mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Solution] Updates Timeline tooltips to use action words / fewer words (#132756)
## [Security Solution] Updates Timeline tooltips to use action words / fewer words - This PR updates the row-level action button tooltips in Timeline, per issue <https://github.com/elastic/kibana/issues/126973>, to use action words / fewer words. This brings the tooltips up to date with the latest [EUI Guidelines](https://elastic.github.io/eui/#/navigation/button/guidelines). - The tooltips now differentiate between events and alerts. (The original tooltips were written before the Security Solution shipped with a detection engine, so there was no prior distinction.) ### Alert tooltips This section contains before / after screenshots for alerts. #### Before: Unpinned alert  #### After: Unpinned alert  #### Before: Pinned alert  #### After: Pinned alert  #### Before: Add a note to an alert  #### After: Add a note to an alert  #### Before: A pinned alert with notes  #### After: A pinned alert with notes  #### Before: A timeline template with alerts  #### After: A timeline template with alerts  ### Event tooltips This section contains before / after screenshots for events. #### Before: Unpinned event  #### After: Unpinned event  #### Before: Pinned event  #### After: Pinned event  #### Before: Add a note to event  #### After: Add a note to an event  #### Before: A pinned event with notes  #### After: A pinned event with notes  #### Before: A timeline template with events  #### After: A timeline template with events  CC: @dimadavid
This commit is contained in:
parent
68a62969d2
commit
899e5cb089
13 changed files with 297 additions and 108 deletions
|
@ -9,7 +9,7 @@ import { mount } from 'enzyme';
|
|||
import React from 'react';
|
||||
|
||||
import { TestProviders, mockTimelineModel, mockTimelineData } from '../../../../../common/mock';
|
||||
import { Actions } from '.';
|
||||
import { Actions, isAlert } from '.';
|
||||
import { mockTimelines } from '../../../../../common/mock/mock_timelines_plugin';
|
||||
import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features';
|
||||
import { mockCasesContract } from '@kbn/cases-plugin/public/mocks';
|
||||
|
@ -221,4 +221,14 @@ describe('Actions', () => {
|
|||
expect(wrapper.find('[data-test-subj="view-in-analyzer"]').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAlert', () => {
|
||||
test('it returns true when the eventType is an alert', () => {
|
||||
expect(isAlert('signal')).toBe(true);
|
||||
});
|
||||
|
||||
test('it returns false when the eventType is NOT an alert', () => {
|
||||
expect(isAlert('raw')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -35,11 +35,15 @@ import {
|
|||
ActionProps,
|
||||
OnPinEvent,
|
||||
TimelineTabs,
|
||||
TimelineEventsType,
|
||||
} from '../../../../../../common/types/timeline';
|
||||
import { timelineActions, timelineSelectors } from '../../../../store/timeline';
|
||||
import { timelineDefaults } from '../../../../store/timeline/defaults';
|
||||
import { isInvestigateInResolverActionEnabled } from '../../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver';
|
||||
|
||||
export const isAlert = (eventType: TimelineEventsType | Omit<TimelineEventsType, 'all'>): boolean =>
|
||||
eventType === 'signal';
|
||||
|
||||
const ActionsContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
@ -221,6 +225,7 @@ const ActionsComponent: React.FC<ActionProps> = ({
|
|||
/>
|
||||
<PinEventAction
|
||||
ariaLabel={i18n.PIN_EVENT_FOR_ROW({ ariaRowindex, columnValues, isEventPinned })}
|
||||
isAlert={isAlert(eventType)}
|
||||
key="pin-event"
|
||||
onPinClicked={handlePinClicked}
|
||||
noteIds={eventIdToNoteIds ? eventIdToNoteIds[eventId] || emptyNotes : emptyNotes}
|
||||
|
|
|
@ -16,6 +16,7 @@ import { TimelineType } from '../../../../../../common/types/timeline';
|
|||
|
||||
interface PinEventActionProps {
|
||||
ariaLabel?: string;
|
||||
isAlert: boolean;
|
||||
noteIds: string[];
|
||||
onPinClicked: () => void;
|
||||
eventIsPinned: boolean;
|
||||
|
@ -24,6 +25,7 @@ interface PinEventActionProps {
|
|||
|
||||
const PinEventActionComponent: React.FC<PinEventActionProps> = ({
|
||||
ariaLabel,
|
||||
isAlert,
|
||||
noteIds,
|
||||
onPinClicked,
|
||||
eventIsPinned,
|
||||
|
@ -33,10 +35,11 @@ const PinEventActionComponent: React.FC<PinEventActionProps> = ({
|
|||
() =>
|
||||
getPinTooltip({
|
||||
isPinned: eventIsPinned,
|
||||
isAlert,
|
||||
eventHasNotes: eventHasNotes(noteIds),
|
||||
timelineType,
|
||||
}),
|
||||
[eventIsPinned, noteIds, timelineType]
|
||||
[eventIsPinned, isAlert, noteIds, timelineType]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -47,6 +50,7 @@ const PinEventActionComponent: React.FC<PinEventActionProps> = ({
|
|||
ariaLabel={ariaLabel}
|
||||
allowUnpinning={!eventHasNotes(noteIds)}
|
||||
data-test-subj="pin-event"
|
||||
isAlert={isAlert}
|
||||
onClick={onPinClicked}
|
||||
pinned={eventIsPinned}
|
||||
timelineType={timelineType}
|
||||
|
|
|
@ -86,7 +86,7 @@ export const getEventsSelectOptions = (): EventsSelectOption[] => [
|
|||
dropdownDisplay: (
|
||||
<PinActionItem>
|
||||
<PinIconContainer>
|
||||
<Pin allowUnpinning={true} pinned={true} />
|
||||
<Pin allowUnpinning={true} isAlert={false} pinned={true} />
|
||||
</PinIconContainer>
|
||||
<DropdownDisplay text={i18n.PIN_SELECTED} />
|
||||
</PinActionItem>
|
||||
|
@ -99,7 +99,7 @@ export const getEventsSelectOptions = (): EventsSelectOption[] => [
|
|||
dropdownDisplay: (
|
||||
<PinActionItem>
|
||||
<PinIconContainer>
|
||||
<Pin allowUnpinning={true} pinned={false} />
|
||||
<Pin allowUnpinning={true} isAlert={false} pinned={false} />
|
||||
</PinIconContainer>
|
||||
<DropdownDisplay text={i18n.UNPIN_SELECTED} />
|
||||
</PinActionItem>
|
||||
|
|
|
@ -196,37 +196,113 @@ describe('helpers', () => {
|
|||
describe('getPinTooltip', () => {
|
||||
test('it indicates the event may NOT be unpinned when `isPinned` is `true` and the event has notes', () => {
|
||||
expect(
|
||||
getPinTooltip({ isPinned: true, eventHasNotes: true, timelineType: TimelineType.default })
|
||||
getPinTooltip({
|
||||
isAlert: false,
|
||||
isPinned: true,
|
||||
eventHasNotes: true,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('This event cannot be unpinned because it has notes');
|
||||
});
|
||||
|
||||
test('it indicates the alert may NOT be unpinned when `isPinned` is `true` and the alert has notes', () => {
|
||||
expect(
|
||||
getPinTooltip({
|
||||
isAlert: true,
|
||||
isPinned: true,
|
||||
eventHasNotes: true,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('This alert cannot be unpinned because it has notes');
|
||||
});
|
||||
|
||||
test('it indicates the event is pinned when `isPinned` is `true` and the event does NOT have notes', () => {
|
||||
expect(
|
||||
getPinTooltip({ isPinned: true, eventHasNotes: false, timelineType: TimelineType.default })
|
||||
).toEqual('Pinned event');
|
||||
getPinTooltip({
|
||||
isAlert: false,
|
||||
isPinned: true,
|
||||
eventHasNotes: false,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('Unpin event');
|
||||
});
|
||||
|
||||
test('it indicates the alert is pinned when `isPinned` is `true` and the alert does NOT have notes', () => {
|
||||
expect(
|
||||
getPinTooltip({
|
||||
isAlert: true,
|
||||
isPinned: true,
|
||||
eventHasNotes: false,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('Unpin alert');
|
||||
});
|
||||
|
||||
test('it indicates the event is NOT pinned when `isPinned` is `false` and the event has notes', () => {
|
||||
expect(
|
||||
getPinTooltip({ isPinned: false, eventHasNotes: true, timelineType: TimelineType.default })
|
||||
).toEqual('Unpinned event');
|
||||
getPinTooltip({
|
||||
isAlert: false,
|
||||
isPinned: false,
|
||||
eventHasNotes: true,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('Pin event');
|
||||
});
|
||||
|
||||
test('it indicates the alert is NOT pinned when `isPinned` is `false` and the alert has notes', () => {
|
||||
expect(
|
||||
getPinTooltip({
|
||||
isAlert: true,
|
||||
isPinned: false,
|
||||
eventHasNotes: true,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('Pin alert');
|
||||
});
|
||||
|
||||
test('it indicates the event is NOT pinned when `isPinned` is `false` and the event does NOT have notes', () => {
|
||||
expect(
|
||||
getPinTooltip({ isPinned: false, eventHasNotes: false, timelineType: TimelineType.default })
|
||||
).toEqual('Unpinned event');
|
||||
getPinTooltip({
|
||||
isAlert: false,
|
||||
isPinned: false,
|
||||
eventHasNotes: false,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('Pin event');
|
||||
});
|
||||
|
||||
test('it indicates the alert is NOT pinned when `isPinned` is `false` and the alert does NOT have notes', () => {
|
||||
expect(
|
||||
getPinTooltip({
|
||||
isAlert: true,
|
||||
isPinned: false,
|
||||
eventHasNotes: false,
|
||||
timelineType: TimelineType.default,
|
||||
})
|
||||
).toEqual('Pin alert');
|
||||
});
|
||||
|
||||
test('it indicates the event is disabled if timelineType is template', () => {
|
||||
expect(
|
||||
getPinTooltip({
|
||||
isAlert: false,
|
||||
isPinned: false,
|
||||
eventHasNotes: false,
|
||||
timelineType: TimelineType.template,
|
||||
})
|
||||
).toEqual('This event may not be pinned while editing a template timeline');
|
||||
});
|
||||
|
||||
test('it indicates the alert is disabled if timelineType is template', () => {
|
||||
expect(
|
||||
getPinTooltip({
|
||||
isAlert: true,
|
||||
isPinned: false,
|
||||
eventHasNotes: false,
|
||||
timelineType: TimelineType.template,
|
||||
})
|
||||
).toEqual('This alert may not be pinned while editing a template timeline');
|
||||
});
|
||||
});
|
||||
|
||||
describe('eventIsPinned', () => {
|
||||
|
|
|
@ -28,22 +28,27 @@ export const stringifyEvent = (ecs: Ecs): string => JSON.stringify(ecs, omitType
|
|||
export const eventHasNotes = (noteIds: string[]): boolean => !isEmpty(noteIds);
|
||||
|
||||
export const getPinTooltip = ({
|
||||
isAlert,
|
||||
isPinned,
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
eventHasNotes,
|
||||
timelineType,
|
||||
}: {
|
||||
isAlert: boolean;
|
||||
isPinned: boolean;
|
||||
eventHasNotes: boolean;
|
||||
timelineType: TimelineTypeLiteral;
|
||||
}) =>
|
||||
timelineType === TimelineType.template
|
||||
? i18n.DISABLE_PIN
|
||||
: isPinned && eventHasNotes
|
||||
? i18n.PINNED_WITH_NOTES
|
||||
: isPinned
|
||||
? i18n.PINNED
|
||||
: i18n.UNPINNED;
|
||||
}) => {
|
||||
if (timelineType === TimelineType.template) {
|
||||
return i18n.DISABLE_PIN(isAlert);
|
||||
} else if (isPinned && eventHasNotes) {
|
||||
return i18n.PINNED_WITH_NOTES(isAlert);
|
||||
} else if (isPinned) {
|
||||
return i18n.PINNED(isAlert);
|
||||
} else {
|
||||
return i18n.UNPINNED(isAlert);
|
||||
}
|
||||
};
|
||||
|
||||
export interface IsPinnedParams {
|
||||
eventId: string;
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const NOTES_TOOLTIP = i18n.translate(
|
||||
'xpack.securitySolution.timeline.body.notes.addOrViewNotesForThisEventTooltip',
|
||||
'xpack.securitySolution.timeline.body.notes.addNoteTooltip',
|
||||
{
|
||||
defaultMessage: 'Add notes for this event',
|
||||
defaultMessage: 'Add note',
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -42,23 +42,24 @@ export const INVESTIGATE = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const UNPINNED = i18n.translate(
|
||||
'xpack.securitySolution.timeline.body.pinning.unpinnedTooltip',
|
||||
{
|
||||
defaultMessage: 'Unpinned event',
|
||||
}
|
||||
);
|
||||
export const UNPINNED = (isAlert: boolean) =>
|
||||
i18n.translate('xpack.securitySolution.timeline.body.pinning.pinTooltip', {
|
||||
values: { isAlert },
|
||||
defaultMessage: 'Pin {isAlert, select, true{alert} other{event}}',
|
||||
});
|
||||
|
||||
export const PINNED = i18n.translate('xpack.securitySolution.timeline.body.pinning.pinnedTooltip', {
|
||||
defaultMessage: 'Pinned event',
|
||||
});
|
||||
export const PINNED = (isAlert: boolean) =>
|
||||
i18n.translate('xpack.securitySolution.timeline.body.pinning.unpinTooltip', {
|
||||
values: { isAlert },
|
||||
defaultMessage: 'Unpin {isAlert, select, true{alert} other{event}}',
|
||||
});
|
||||
|
||||
export const PINNED_WITH_NOTES = i18n.translate(
|
||||
'xpack.securitySolution.timeline.body.pinning.pinnnedWithNotesTooltip',
|
||||
{
|
||||
defaultMessage: 'This event cannot be unpinned because it has notes',
|
||||
}
|
||||
);
|
||||
export const PINNED_WITH_NOTES = (isAlert: boolean) =>
|
||||
i18n.translate('xpack.securitySolution.timeline.body.pinning.pinnnedWithNotesTooltip', {
|
||||
values: { isAlert },
|
||||
defaultMessage:
|
||||
'This {isAlert, select, true{alert} other{event}} cannot be unpinned because it has notes',
|
||||
});
|
||||
|
||||
export const SORTED_ASCENDING = i18n.translate(
|
||||
'xpack.securitySolution.timeline.body.sort.sortedAscendingTooltip',
|
||||
|
@ -74,12 +75,12 @@ export const SORTED_DESCENDING = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const DISABLE_PIN = i18n.translate(
|
||||
'xpack.securitySolution.timeline.body.pinning.disablePinnnedTooltip',
|
||||
{
|
||||
defaultMessage: 'This event may not be pinned while editing a template timeline',
|
||||
}
|
||||
);
|
||||
export const DISABLE_PIN = (isAlert: boolean) =>
|
||||
i18n.translate('xpack.securitySolution.timeline.body.pinning.disablePinnnedTooltip', {
|
||||
values: { isAlert },
|
||||
defaultMessage:
|
||||
'This {isAlert, select, true{alert} other{event}} may not be pinned while editing a template timeline',
|
||||
});
|
||||
|
||||
export const VIEW_DETAILS = i18n.translate(
|
||||
'xpack.securitySolution.timeline.body.actions.viewDetailsAriaLabel',
|
||||
|
|
|
@ -10,13 +10,67 @@ import React from 'react';
|
|||
|
||||
import { TimelineType } from '../../../../../common/types/timeline';
|
||||
|
||||
import { getPinIcon, Pin } from '.';
|
||||
import { getDefaultAriaLabel, getPinIcon, Pin } from '.';
|
||||
|
||||
interface ButtonIcon {
|
||||
isDisabled: boolean;
|
||||
}
|
||||
|
||||
describe('pin', () => {
|
||||
describe('getDefaultAriaLabel', () => {
|
||||
test('it returns the expected label for a timeline template event', () => {
|
||||
const isAlert = false;
|
||||
const isTemplate = true;
|
||||
const isPinned = false;
|
||||
|
||||
expect(getDefaultAriaLabel({ isAlert, isTemplate, isPinned })).toEqual(
|
||||
'This event may not be pinned while editing a template timeline'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns the expected label for a timeline template alert', () => {
|
||||
const isAlert = true;
|
||||
const isTemplate = true;
|
||||
const isPinned = false;
|
||||
|
||||
expect(getDefaultAriaLabel({ isAlert, isTemplate, isPinned })).toEqual(
|
||||
'This alert may not be pinned while editing a template timeline'
|
||||
);
|
||||
});
|
||||
|
||||
test('it returns the expected label for a pinned event', () => {
|
||||
const isAlert = false;
|
||||
const isTemplate = false;
|
||||
const isPinned = true;
|
||||
|
||||
expect(getDefaultAriaLabel({ isAlert, isTemplate, isPinned })).toEqual('Unpin event');
|
||||
});
|
||||
|
||||
test('it returns the expected label for a pinned alert', () => {
|
||||
const isAlert = true;
|
||||
const isTemplate = false;
|
||||
const isPinned = true;
|
||||
|
||||
expect(getDefaultAriaLabel({ isAlert, isTemplate, isPinned })).toEqual('Unpin alert');
|
||||
});
|
||||
|
||||
test('it returns the expected label for a unpinned event', () => {
|
||||
const isAlert = false;
|
||||
const isTemplate = false;
|
||||
const isPinned = false;
|
||||
|
||||
expect(getDefaultAriaLabel({ isAlert, isTemplate, isPinned })).toEqual('Pin event');
|
||||
});
|
||||
|
||||
test('it returns the expected label for a unpinned alert', () => {
|
||||
const isAlert = true;
|
||||
const isTemplate = false;
|
||||
const isPinned = false;
|
||||
|
||||
expect(getDefaultAriaLabel({ isAlert, isTemplate, isPinned })).toEqual('Pin alert');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPinRotation', () => {
|
||||
test('it returns a filled pin when pinned is true', () => {
|
||||
expect(getPinIcon(true)).toEqual('pinFilled');
|
||||
|
@ -28,10 +82,11 @@ describe('pin', () => {
|
|||
});
|
||||
|
||||
describe('disabled button behavior', () => {
|
||||
test('the button is enabled when allowUnpinning is true, and timelineType is NOT `template` (the default)', () => {
|
||||
test('the button is enabled for an event when allowUnpinning is true, and timelineType is NOT `template` (the default)', () => {
|
||||
const isAlert = false;
|
||||
const allowUnpinning = true;
|
||||
const wrapper = mount(
|
||||
<Pin allowUnpinning={allowUnpinning} onClick={jest.fn()} pinned={false} />
|
||||
<Pin allowUnpinning={allowUnpinning} isAlert={isAlert} onClick={jest.fn()} pinned={false} />
|
||||
);
|
||||
|
||||
expect(
|
||||
|
@ -39,10 +94,23 @@ describe('pin', () => {
|
|||
).toBe(false);
|
||||
});
|
||||
|
||||
test('the button is disabled when allowUnpinning is false, and timelineType is NOT `template` (the default)', () => {
|
||||
test('the button is enabled for an alert when allowUnpinning is true, and timelineType is NOT `template` (the default)', () => {
|
||||
const isAlert = true;
|
||||
const allowUnpinning = true;
|
||||
const wrapper = mount(
|
||||
<Pin allowUnpinning={allowUnpinning} isAlert={isAlert} onClick={jest.fn()} pinned={false} />
|
||||
);
|
||||
|
||||
expect(
|
||||
(wrapper.find('[data-test-subj="pin"]').first().props() as ButtonIcon).isDisabled
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test('the button is disabled for an event when allowUnpinning is false, and timelineType is NOT `template` (the default)', () => {
|
||||
const isAlert = false;
|
||||
const allowUnpinning = false;
|
||||
const wrapper = mount(
|
||||
<Pin allowUnpinning={allowUnpinning} onClick={jest.fn()} pinned={false} />
|
||||
<Pin allowUnpinning={allowUnpinning} isAlert={isAlert} onClick={jest.fn()} pinned={false} />
|
||||
);
|
||||
|
||||
expect(
|
||||
|
@ -50,12 +118,26 @@ describe('pin', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
|
||||
test('the button is disabled when allowUnpinning is true, and timelineType is `template`', () => {
|
||||
test('the button is disabled for an alert when allowUnpinning is false, and timelineType is NOT `template` (the default)', () => {
|
||||
const isAlert = true;
|
||||
const allowUnpinning = false;
|
||||
const wrapper = mount(
|
||||
<Pin allowUnpinning={allowUnpinning} isAlert={isAlert} onClick={jest.fn()} pinned={false} />
|
||||
);
|
||||
|
||||
expect(
|
||||
(wrapper.find('[data-test-subj="pin"]').first().props() as ButtonIcon).isDisabled
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('the button is disabled for an event when allowUnpinning is true, and timelineType is `template`', () => {
|
||||
const isAlert = false;
|
||||
const allowUnpinning = true;
|
||||
const timelineType = TimelineType.template;
|
||||
const wrapper = mount(
|
||||
<Pin
|
||||
allowUnpinning={allowUnpinning}
|
||||
isAlert={isAlert}
|
||||
onClick={jest.fn()}
|
||||
pinned={false}
|
||||
timelineType={timelineType}
|
||||
|
@ -67,12 +149,52 @@ describe('pin', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
|
||||
test('the button is disabled when allowUnpinning is false, and timelineType is `template`', () => {
|
||||
test('the button is disabled for an alert when allowUnpinning is true, and timelineType is `template`', () => {
|
||||
const isAlert = true;
|
||||
const allowUnpinning = true;
|
||||
const timelineType = TimelineType.template;
|
||||
const wrapper = mount(
|
||||
<Pin
|
||||
allowUnpinning={allowUnpinning}
|
||||
isAlert={isAlert}
|
||||
onClick={jest.fn()}
|
||||
pinned={false}
|
||||
timelineType={timelineType}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
(wrapper.find('[data-test-subj="pin"]').first().props() as ButtonIcon).isDisabled
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('the button is disabled for an event when allowUnpinning is false, and timelineType is `template`', () => {
|
||||
const isAlert = false;
|
||||
const allowUnpinning = false;
|
||||
const timelineType = TimelineType.template;
|
||||
const wrapper = mount(
|
||||
<Pin
|
||||
allowUnpinning={allowUnpinning}
|
||||
isAlert={isAlert}
|
||||
onClick={jest.fn()}
|
||||
pinned={false}
|
||||
timelineType={timelineType}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
(wrapper.find('[data-test-subj="pin"]').first().props() as ButtonIcon).isDisabled
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('the button is disabled for an alert when allowUnpinning is false, and timelineType is `template`', () => {
|
||||
const isAlert = true;
|
||||
const allowUnpinning = false;
|
||||
const timelineType = TimelineType.template;
|
||||
const wrapper = mount(
|
||||
<Pin
|
||||
allowUnpinning={allowUnpinning}
|
||||
isAlert={isAlert}
|
||||
onClick={jest.fn()}
|
||||
pinned={false}
|
||||
timelineType={timelineType}
|
||||
|
|
|
@ -20,15 +20,38 @@ export const getPinIcon = (pinned: boolean): PinIcon => (pinned ? 'pinFilled' :
|
|||
interface Props {
|
||||
ariaLabel?: string;
|
||||
allowUnpinning: boolean;
|
||||
isAlert: boolean;
|
||||
timelineType?: TimelineTypeLiteral;
|
||||
onClick?: () => void;
|
||||
pinned: boolean;
|
||||
}
|
||||
|
||||
export const getDefaultAriaLabel = ({
|
||||
isAlert,
|
||||
isTemplate,
|
||||
isPinned,
|
||||
}: {
|
||||
isAlert: boolean;
|
||||
isTemplate: boolean;
|
||||
isPinned: boolean;
|
||||
}): string => {
|
||||
if (isTemplate) {
|
||||
return i18n.DISABLE_PIN(isAlert);
|
||||
} else if (isPinned) {
|
||||
return i18n.PINNED(isAlert);
|
||||
} else {
|
||||
return i18n.UNPINNED(isAlert);
|
||||
}
|
||||
};
|
||||
|
||||
export const Pin = React.memo<Props>(
|
||||
({ ariaLabel, allowUnpinning, onClick = noop, pinned, timelineType }) => {
|
||||
({ ariaLabel, allowUnpinning, isAlert, onClick = noop, pinned, timelineType }) => {
|
||||
const isTemplate = timelineType === TimelineType.template;
|
||||
const defaultAriaLabel = isTemplate ? i18n.DISABLE_PIN : pinned ? i18n.PINNED : i18n.UNPINNED;
|
||||
const defaultAriaLabel = getDefaultAriaLabel({
|
||||
isAlert,
|
||||
isTemplate,
|
||||
isPinned: pinned,
|
||||
});
|
||||
const pinAriaLabel = ariaLabel != null ? ariaLabel : defaultAriaLabel;
|
||||
|
||||
return (
|
||||
|
|
|
@ -7,13 +7,6 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const NOTES_TOOLTIP = i18n.translate(
|
||||
'xpack.timelines.timeline.body.notes.addOrViewNotesForThisEventTooltip',
|
||||
{
|
||||
defaultMessage: 'Add notes for this event',
|
||||
}
|
||||
);
|
||||
|
||||
export const TGRID_BODY_ARIA_LABEL = i18n.translate('xpack.timelines.tgrid.body.ariaLabel', {
|
||||
defaultMessage: 'Alerts',
|
||||
});
|
||||
|
@ -39,14 +32,6 @@ export const INVESTIGATE = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const UNPINNED = i18n.translate('xpack.timelines.timeline.body.pinning.unpinnedTooltip', {
|
||||
defaultMessage: 'Unpinned event',
|
||||
});
|
||||
|
||||
export const PINNED = i18n.translate('xpack.timelines.timeline.body.pinning.pinnedTooltip', {
|
||||
defaultMessage: 'Pinned event',
|
||||
});
|
||||
|
||||
export const PINNED_WITH_NOTES = i18n.translate(
|
||||
'xpack.timelines.timeline.body.pinning.pinnnedWithNotesTooltip',
|
||||
{
|
||||
|
@ -157,21 +142,6 @@ export const ADD_NOTES_FOR_ROW = ({
|
|||
'Add notes for the event in row {ariaRowindex} to timeline, with columns {columnValues}',
|
||||
});
|
||||
|
||||
export const PIN_EVENT_FOR_ROW = ({
|
||||
ariaRowindex,
|
||||
columnValues,
|
||||
isEventPinned,
|
||||
}: {
|
||||
ariaRowindex: number;
|
||||
columnValues: string;
|
||||
isEventPinned: boolean;
|
||||
}) =>
|
||||
i18n.translate('xpack.timelines.timeline.body.actions.pinEventForRowAriaLabel', {
|
||||
values: { ariaRowindex, columnValues, isEventPinned },
|
||||
defaultMessage:
|
||||
'{isEventPinned, select, false {Pin} true {Unpin}} the event in row {ariaRowindex} to timeline, with columns {columnValues}',
|
||||
});
|
||||
|
||||
export const TIMELINE_TOGGLE_BUTTON_ARIA_LABEL = ({
|
||||
isOpen,
|
||||
title,
|
||||
|
|
|
@ -26445,12 +26445,7 @@
|
|||
"xpack.securitySolution.timeline.body.actions.viewDetailsForRowAriaLabel": "Afficher les détails pour l'alerte ou l'événement de la ligne {ariaRowindex}, avec les colonnes {columnValues}",
|
||||
"xpack.securitySolution.timeline.body.actions.viewSummaryLabel": "Afficher le résumé",
|
||||
"xpack.securitySolution.timeline.body.copyToClipboardButtonLabel": "Copier dans le Presse-papiers",
|
||||
"xpack.securitySolution.timeline.body.notes.addOrViewNotesForThisEventTooltip": "Ajouter des notes pour cet évènement",
|
||||
"xpack.securitySolution.timeline.body.notes.disableEventTooltip": "Les notes ne peuvent pas être ajoutées ici lors de la modification d'une chronologie de modèle",
|
||||
"xpack.securitySolution.timeline.body.pinning.disablePinnnedTooltip": "Cet événement ne peut pas être épinglé lors de la modification d'une chronologie de modèle",
|
||||
"xpack.securitySolution.timeline.body.pinning.pinnedTooltip": "Événement épinglé",
|
||||
"xpack.securitySolution.timeline.body.pinning.pinnnedWithNotesTooltip": "Cet événement ne peut pas être désépinglé, car il contient des notes",
|
||||
"xpack.securitySolution.timeline.body.pinning.unpinnedTooltip": "Événement désépinglé",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.askedForDescription": "demandé",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.responseCodeDescription": "code de réponse :",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.viaDescription": "via",
|
||||
|
@ -27973,18 +27968,14 @@
|
|||
"xpack.timelines.timeline.body.actions.investigateInResolverTooltip": "Analyser l'événement",
|
||||
"xpack.timelines.timeline.body.actions.investigateLabel": "Investiguer",
|
||||
"xpack.timelines.timeline.body.actions.moreActionsForRowAriaLabel": "Sélectionner davantage d'actions pour l'alerte ou l'événement de la ligne {ariaRowindex}, avec les colonnes {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.pinEventForRowAriaLabel": "{isEventPinned, select, false {Épingler} true {Désépingler}} l'événement de la ligne {ariaRowindex} {isEventPinned, select, false{dans} true {de}} la chronologie, avec les colonnes {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.sendAlertToTimelineForRowAriaLabel": "Envoyer l'alerte de la ligne {ariaRowindex} à la chronologie, avec les colonnes {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.viewDetailsAriaLabel": "Afficher les détails",
|
||||
"xpack.timelines.timeline.body.actions.viewDetailsForRowAriaLabel": "Afficher les détails pour l'alerte ou l'événement de la ligne {ariaRowindex}, avec les colonnes {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.viewSummaryLabel": "Afficher le résumé",
|
||||
"xpack.timelines.timeline.body.copyToClipboardButtonLabel": "Copier dans le Presse-papiers",
|
||||
"xpack.timelines.timeline.body.notes.addOrViewNotesForThisEventTooltip": "Ajouter des notes pour cet évènement",
|
||||
"xpack.timelines.timeline.body.notes.disableEventTooltip": "Les notes ne peuvent pas être ajoutées ici lors de la modification d'une chronologie de modèle",
|
||||
"xpack.timelines.timeline.body.pinning.disablePinnnedTooltip": "Cet événement ne peut pas être épinglé lors de la modification d'une chronologie de modèle",
|
||||
"xpack.timelines.timeline.body.pinning.pinnedTooltip": "Événement épinglé",
|
||||
"xpack.timelines.timeline.body.pinning.pinnnedWithNotesTooltip": "Cet événement ne peut pas être désépinglé, car il contient des notes",
|
||||
"xpack.timelines.timeline.body.pinning.unpinnedTooltip": "Événement désépinglé",
|
||||
"xpack.timelines.timeline.body.sort.sortedAscendingTooltip": "Trié par ordre croissant",
|
||||
"xpack.timelines.timeline.body.sort.sortedDescendingTooltip": "Trié par ordre décroissant",
|
||||
"xpack.timelines.timeline.categoryTooltip": "Catégorie",
|
||||
|
|
|
@ -26599,13 +26599,8 @@
|
|||
"xpack.securitySolution.timeline.body.actions.viewDetailsForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のアラートまたはイベントの詳細を表示",
|
||||
"xpack.securitySolution.timeline.body.actions.viewSummaryLabel": "概要を表示",
|
||||
"xpack.securitySolution.timeline.body.copyToClipboardButtonLabel": "クリップボードにコピー",
|
||||
"xpack.securitySolution.timeline.body.notes.addOrViewNotesForThisEventTooltip": "このイベントのメモを追加します",
|
||||
"xpack.securitySolution.timeline.body.notes.disableEventTooltip": "テンプレートタイムラインの編集中には、メモが追加されない場合があります",
|
||||
"xpack.securitySolution.timeline.body.openSessionViewLabel": "セッションビューを開く",
|
||||
"xpack.securitySolution.timeline.body.pinning.disablePinnnedTooltip": "テンプレートタイムラインの編集中には、このイベントがピン留めされない場合があります",
|
||||
"xpack.securitySolution.timeline.body.pinning.pinnedTooltip": "ピン付けされたイベント",
|
||||
"xpack.securitySolution.timeline.body.pinning.pinnnedWithNotesTooltip": "イベントにメモがあり、ピンを外すことができません",
|
||||
"xpack.securitySolution.timeline.body.pinning.unpinnedTooltip": "ピン付け解除されたイベント",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.askedForDescription": "要求された",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.responseCodeDescription": "応答コード:",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.viaDescription": "経由",
|
||||
|
@ -28133,18 +28128,14 @@
|
|||
"xpack.timelines.timeline.body.actions.investigateInResolverTooltip": "イベントを分析します",
|
||||
"xpack.timelines.timeline.body.actions.investigateLabel": "調査",
|
||||
"xpack.timelines.timeline.body.actions.moreActionsForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のアラートまたはイベントのその他のアクションを選択",
|
||||
"xpack.timelines.timeline.body.actions.pinEventForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のイベントを{isEventPinned, select, false {固定} true {固定解除}}",
|
||||
"xpack.timelines.timeline.body.actions.sendAlertToTimelineForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のイベントのアラートを送信",
|
||||
"xpack.timelines.timeline.body.actions.viewDetailsAriaLabel": "詳細を表示",
|
||||
"xpack.timelines.timeline.body.actions.viewDetailsForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のアラートまたはイベントの詳細を表示",
|
||||
"xpack.timelines.timeline.body.actions.viewSummaryLabel": "概要を表示",
|
||||
"xpack.timelines.timeline.body.copyToClipboardButtonLabel": "クリップボードにコピー",
|
||||
"xpack.timelines.timeline.body.notes.addOrViewNotesForThisEventTooltip": "このイベントのメモを追加します",
|
||||
"xpack.timelines.timeline.body.notes.disableEventTooltip": "テンプレートタイムラインの編集中には、メモが追加されない場合があります",
|
||||
"xpack.timelines.timeline.body.pinning.disablePinnnedTooltip": "テンプレートタイムラインの編集中には、このイベントがピン留めされない場合があります",
|
||||
"xpack.timelines.timeline.body.pinning.pinnedTooltip": "ピン付けされたイベント",
|
||||
"xpack.timelines.timeline.body.pinning.pinnnedWithNotesTooltip": "イベントにメモがあり、ピンを外すことができません",
|
||||
"xpack.timelines.timeline.body.pinning.unpinnedTooltip": "ピン付け解除されたイベント",
|
||||
"xpack.timelines.timeline.body.sort.sortedAscendingTooltip": "昇順で並べ替えます",
|
||||
"xpack.timelines.timeline.body.sort.sortedDescendingTooltip": "降順で並べ替えます",
|
||||
"xpack.timelines.timeline.categoryTooltip": "カテゴリー",
|
||||
|
|
|
@ -26632,13 +26632,8 @@
|
|||
"xpack.securitySolution.timeline.body.actions.viewDetailsForRowAriaLabel": "查看第 {ariaRowindex} 行的告警或事件的详细信息,其中列为 {columnValues}",
|
||||
"xpack.securitySolution.timeline.body.actions.viewSummaryLabel": "查看摘要",
|
||||
"xpack.securitySolution.timeline.body.copyToClipboardButtonLabel": "复制到剪贴板",
|
||||
"xpack.securitySolution.timeline.body.notes.addOrViewNotesForThisEventTooltip": "为此事件添加备注",
|
||||
"xpack.securitySolution.timeline.body.notes.disableEventTooltip": "编辑模板时间线时无法在此处添加备注",
|
||||
"xpack.securitySolution.timeline.body.openSessionViewLabel": "打开会话视图",
|
||||
"xpack.securitySolution.timeline.body.pinning.disablePinnnedTooltip": "编辑模板时间线时无法置顶此事件",
|
||||
"xpack.securitySolution.timeline.body.pinning.pinnedTooltip": "置顶事件",
|
||||
"xpack.securitySolution.timeline.body.pinning.pinnnedWithNotesTooltip": "此事件无法取消置顶,因为其有备注",
|
||||
"xpack.securitySolution.timeline.body.pinning.unpinnedTooltip": "取消置顶的事件",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.askedForDescription": "请求过",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.responseCodeDescription": "响应代码:",
|
||||
"xpack.securitySolution.timeline.body.renderers.dns.viaDescription": "通过",
|
||||
|
@ -28166,18 +28161,14 @@
|
|||
"xpack.timelines.timeline.body.actions.investigateInResolverTooltip": "分析事件",
|
||||
"xpack.timelines.timeline.body.actions.investigateLabel": "调查",
|
||||
"xpack.timelines.timeline.body.actions.moreActionsForRowAriaLabel": "为第 {ariaRowindex} 行中的告警或事件选择更多操作,其中列为 {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.pinEventForRowAriaLabel": "将第 {ariaRowindex} 行的事件{isEventPinned, select, false {固定} true {取消固定}}到时间线,其中列为 {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.sendAlertToTimelineForRowAriaLabel": "将第 {ariaRowindex} 行的告警发送到时间线,其中列为 {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.viewDetailsAriaLabel": "查看详情",
|
||||
"xpack.timelines.timeline.body.actions.viewDetailsForRowAriaLabel": "查看第 {ariaRowindex} 行的告警或事件的详细信息,其中列为 {columnValues}",
|
||||
"xpack.timelines.timeline.body.actions.viewSummaryLabel": "查看摘要",
|
||||
"xpack.timelines.timeline.body.copyToClipboardButtonLabel": "复制到剪贴板",
|
||||
"xpack.timelines.timeline.body.notes.addOrViewNotesForThisEventTooltip": "为此事件添加备注",
|
||||
"xpack.timelines.timeline.body.notes.disableEventTooltip": "编辑模板时间线时无法在此处添加备注",
|
||||
"xpack.timelines.timeline.body.pinning.disablePinnnedTooltip": "编辑模板时间线时无法置顶此事件",
|
||||
"xpack.timelines.timeline.body.pinning.pinnedTooltip": "置顶事件",
|
||||
"xpack.timelines.timeline.body.pinning.pinnnedWithNotesTooltip": "此事件无法取消置顶,因为其有备注",
|
||||
"xpack.timelines.timeline.body.pinning.unpinnedTooltip": "取消置顶的事件",
|
||||
"xpack.timelines.timeline.body.sort.sortedAscendingTooltip": "已升序",
|
||||
"xpack.timelines.timeline.body.sort.sortedDescendingTooltip": "已降序",
|
||||
"xpack.timelines.timeline.categoryTooltip": "类别",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue