Skip to content

Commit

Permalink
fix description label
Browse files Browse the repository at this point in the history
  • Loading branch information
angorayc committed Oct 28, 2020
1 parent aa33e3f commit acc014b
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,36 +101,9 @@ describe('TimelineTitleAndDescription', () => {
expect(component.find('[data-test-subj="save-timeline-description"]').exists()).toEqual(true);
});

test('Show discardTimelineButton', () => {
test('Show close button', () => {
const component = shallow(<TimelineTitleAndDescription {...props} />);
expect(component.find('[data-test-subj="mock-discard-button"]').exists()).toEqual(true);
});

test('get discardTimelineButton with correct props', () => {
shallow(<TimelineTitleAndDescription {...props} />);
expect(mockGetButton).toBeCalledWith({
title: i18n.DISCARD_TIMELINE,
outline: true,
iconType: '',
fill: false,
});
});

test('get discardTimelineTemplateButton with correct props', () => {
(useShallowEqualSelector as jest.Mock).mockReturnValue({
description: 'xxxx',
isSaving: true,
savedObjectId: null,
title: 'my timeline',
timelineType: TimelineType.template,
});
shallow(<TimelineTitleAndDescription {...props} />);
expect(mockGetButton).toBeCalledWith({
title: i18n.DISCARD_TIMELINE_TEMPLATE,
outline: true,
iconType: '',
fill: false,
});
expect(component.find('[data-test-subj="close-button"]').exists()).toEqual(true);
});

test('Show saveButton', () => {
Expand Down Expand Up @@ -205,9 +178,79 @@ describe('TimelineTitleAndDescription', () => {
expect(component.find('[data-test-subj="save-timeline-description"]').exists()).toEqual(true);
});

test('Show saveButton', () => {
const component = shallow(<TimelineTitleAndDescription {...props} />);
expect(component.find('[data-test-subj="save-button"]').exists()).toEqual(true);
});
});

describe('showWarning', () => {
const props = {
timelineId: 'timeline-1',
toggleSaveTimeline: jest.fn(),
onSaveTimeline: jest.fn(),
updateTitle: jest.fn(),
updateDescription: jest.fn(),
showWarning: true,
};

const mockGetButton = jest.fn().mockReturnValue(<div data-test-subj="mock-discard-button" />);

beforeEach(() => {
(useShallowEqualSelector as jest.Mock).mockReturnValue({
description: '',
isSaving: true,
savedObjectId: null,
title: 'my timeline',
timelineType: TimelineType.default,
showWarnging: true,
});
(useCreateTimelineButton as jest.Mock).mockReturnValue({
getButton: mockGetButton,
});
});

afterEach(() => {
(useShallowEqualSelector as jest.Mock).mockReset();
(useCreateTimelineButton as jest.Mock).mockReset();
mockGetButton.mockClear();
});

test('Show EuiCallOut', () => {
const component = shallow(<TimelineTitleAndDescription {...props} />);
expect(component.find('[data-test-subj="save-timeline-callout"]').exists()).toEqual(true);
});

test('Show discardTimelineButton', () => {
const component = shallow(<TimelineTitleAndDescription {...props} />);
expect(component.find('[data-test-subj="mock-discard-button"]').exists()).toEqual(false);
expect(component.find('[data-test-subj="mock-discard-button"]').exists()).toEqual(true);
});

test('get discardTimelineButton with correct props', () => {
shallow(<TimelineTitleAndDescription {...props} />);
expect(mockGetButton).toBeCalledWith({
title: i18n.DISCARD_TIMELINE,
outline: true,
iconType: '',
fill: false,
});
});

test('get discardTimelineTemplateButton with correct props', () => {
(useShallowEqualSelector as jest.Mock).mockReturnValue({
description: 'xxxx',
isSaving: true,
savedObjectId: null,
title: 'my timeline',
timelineType: TimelineType.template,
});
shallow(<TimelineTitleAndDescription {...props} />);
expect(mockGetButton).toBeCalledWith({
title: i18n.DISCARD_TIMELINE_TEMPLATE,
outline: true,
iconType: '',
fill: false,
});
});

test('Show saveButton', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EuiModalHeader,
EuiSpacer,
EuiProgress,
EuiCallOut,
} from '@elastic/eui';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { useDispatch } from 'react-redux';
Expand All @@ -22,11 +23,12 @@ import { useShallowEqualSelector } from '../../../../common/hooks/use_selector';
import { timelineActions, timelineSelectors } from '../../../../timelines/store/timeline';
import { TimelineInput } from '../../../store/timeline/actions';
import { Description, Name, UpdateTitle, UpdateDescription } from '../properties/helpers';
import { TIMELINE_TITLE, DESCRIPTION } from '../properties/translations';
import { TIMELINE_TITLE, DESCRIPTION, OPTIONAL } from '../properties/translations';
import { useCreateTimelineButton } from '../properties/use_create_timeline';
import * as i18n from './translations';

interface TimelineTitleAndDescriptionProps {
showWarning?: boolean;
timelineId: string;
toggleSaveTimeline: () => void;
updateTitle: UpdateTitle;
Expand Down Expand Up @@ -57,8 +59,11 @@ const usePrevious = (value: unknown) => {
return ref.current;
};

// when showWarning equals to true,
// the modal is used as a reminder for users to save / discard
// the unsaved timeline / template
export const TimelineTitleAndDescription = React.memo<TimelineTitleAndDescriptionProps>(
({ timelineId, toggleSaveTimeline, updateTitle, updateDescription }) => {
({ timelineId, toggleSaveTimeline, updateTitle, updateDescription, showWarning }) => {
const timeline = useShallowEqualSelector((state) =>
timelineSelectors.selectTimeline(state, timelineId)
);
Expand Down Expand Up @@ -111,12 +116,18 @@ export const TimelineTitleAndDescription = React.memo<TimelineTitleAndDescriptio
: i18n.NAME_TIMELINE;

const saveButtonTitle =
savedObjectId == null
savedObjectId == null && showWarning
? timelineType === TimelineType.template
? i18n.SAVE_TIMELINE_TEMPLATE
: i18n.SAVE_TIMELINE
: i18n.SAVE;

const calloutMessage = useMemo(() => i18n.UNSAVED_TIMELINE_WARNING(timelineType), [
timelineType,
]);

const descriptionLabel = savedObjectId == null ? `${DESCRIPTION} (${OPTIONAL})` : DESCRIPTION;

return (
<>
{isSaving && (
Expand All @@ -125,13 +136,24 @@ export const TimelineTitleAndDescription = React.memo<TimelineTitleAndDescriptio
<EuiModalHeader data-test-subj="modal-header">{modalHeader}</EuiModalHeader>

<Wrapper>
{showWarning && (
<EuiFlexItem grow={true}>
<EuiCallOut
title={calloutMessage}
color="danger"
iconType="alert"
data-test-subj="save-timeline-callout"
/>
</EuiFlexItem>
)}
<EuiFlexItem grow={true}>
<EuiFormRow label={TIMELINE_TITLE}>
<Name
autoFocus={true}
className="timeline-modal-title"
disableTooltip={true}
disableAutoSave={true}
disabled={isSaving}
data-test-subj="save-timeline-name"
timelineId={timelineId}
timelineType={timelineType}
Expand All @@ -144,12 +166,13 @@ export const TimelineTitleAndDescription = React.memo<TimelineTitleAndDescriptio
<EuiSpacer />
</EuiFlexItem>
<EuiFlexItem grow={true}>
<EuiFormRow label={DESCRIPTION}>
<EuiFormRow label={descriptionLabel}>
<Description
data-test-subj="save-timeline-description"
description={description}
disableTooltip={true}
disableAutoSave={true}
disabled={isSaving}
timelineId={timelineId}
updateDescription={updateDescription}
isTextArea={true}
Expand All @@ -161,17 +184,22 @@ export const TimelineTitleAndDescription = React.memo<TimelineTitleAndDescriptio
<EuiFlexItem grow={false}>
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false} component="span">
{savedObjectId == null ? (
{savedObjectId == null && showWarning ? (
discardTimelineButton
) : (
<EuiButton fill={false} onClick={toggleSaveTimeline}>
<EuiButton
fill={false}
onClick={toggleSaveTimeline}
isDisabled={isSaving}
data-test-subj="close-button"
>
{i18n.CLOSE_MODAL}
</EuiButton>
)}
</EuiFlexItem>
<EuiFlexItem grow={false} component="span">
<EuiButton
isDisabled={title.trim().length === 0}
isDisabled={title.trim().length === 0 || isSaving}
fill={true}
onClick={handleClick}
data-test-subj="save-button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import { i18n } from '@kbn/i18n';
import { TimelineType, TimelineTypeLiteral } from '../../../../../common/types/timeline';

export const CALL_OUT_UNAUTHORIZED_MSG = i18n.translate(
'xpack.securitySolution.timeline.callOut.unauthorized.message.description',
Expand Down Expand Up @@ -74,3 +75,9 @@ export const CLOSE_MODAL = i18n.translate(
defaultMessage: 'Close',
}
);

export const UNSAVED_TIMELINE_WARNING = (timelineType: TimelineTypeLiteral) =>
i18n.translate('xpack.securitySolution.timeline.saveTimeline.modal.warning.title', {
values: { timeline: timelineType === TimelineType.template ? 'Timeline template' : 'Timeline' },
defaultMessage: 'You have an unsaved {timeline}, do you wish to save it?',
});
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ interface DescriptionProps {
isTextArea?: boolean;
disableAutoSave?: boolean;
disableTooltip?: boolean;
disabled?: boolean;
marginRight?: number;
}

Expand All @@ -144,6 +145,7 @@ export const Description = React.memo<DescriptionProps>(
isTextArea = false,
disableAutoSave = false,
disableTooltip = false,
disabled = false,
marginRight,
}) => {
const onDescriptionChanged = useCallback(
Expand All @@ -152,6 +154,7 @@ export const Description = React.memo<DescriptionProps>(
},
[updateDescription, disableAutoSave, timelineId]
);

const inputField = useMemo(
() =>
isTextArea ? (
Expand All @@ -162,6 +165,7 @@ export const Description = React.memo<DescriptionProps>(
onChange={onDescriptionChanged}
placeholder={i18n.DESCRIPTION}
value={description}
disabled={disabled}
/>
) : (
<EuiFieldText
Expand All @@ -174,7 +178,7 @@ export const Description = React.memo<DescriptionProps>(
value={description}
/>
),
[description, isTextArea, onDescriptionChanged]
[description, isTextArea, onDescriptionChanged, disabled]
);
return (
<DescriptionContainer data-test-subj="description-container" marginRight={marginRight}>
Expand All @@ -199,6 +203,7 @@ interface NameProps {
className?: string;
disableAutoSave?: boolean;
disableTooltip?: boolean;
disabled?: boolean;
timelineId: string;
timelineType: TimelineType;
title: string;
Expand All @@ -213,6 +218,7 @@ export const Name = React.memo<NameProps>(
className = TIMELINE_TITLE_CLASSNAME,
disableAutoSave = false,
disableTooltip = false,
disabled = false,
timelineId,
timelineType,
title,
Expand Down Expand Up @@ -243,6 +249,7 @@ export const Name = React.memo<NameProps>(
<NameField
aria-label={i18n.TIMELINE_TITLE}
data-test-subj="timeline-title"
disabled={disabled}
onChange={handleChange}
placeholder={
timelineType === TimelineType.template ? i18n.UNTITLED_TEMPLATE : i18n.UNTITLED_TIMELINE
Expand All @@ -254,7 +261,7 @@ export const Name = React.memo<NameProps>(
className={className}
/>
),
[handleChange, marginRight, timelineType, title, width, className]
[handleChange, marginRight, timelineType, title, width, className, disabled]
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,10 @@ export const UNLOCK_SYNC_MAIN_DATE_PICKER_ARIA = i18n.translate(
defaultMessage: 'Unlock date picker to global date picker',
}
);

export const OPTIONAL = i18n.translate(
'xpack.securitySolution.timeline.properties.timelineDescriptionOptional',
{
defaultMessage: 'Optional',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@ export const useCreateTimelineButton = ({
title,
iconType = 'plusInCircle',
fill = true,
isDisabled = false,
}: {
outline?: boolean;
title?: string;
iconType?: string;
fill?: boolean;
isDisabled?: boolean;
}) => {
const buttonProps = {
iconType,
Expand Down

0 comments on commit acc014b

Please sign in to comment.