[MM-60213] Migrate tooltips of "components/toast" to WithTooltip (#28001)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
21b923b554
Коммит
c67a5b10e6
@@ -71,7 +71,6 @@ export function TeamProfile({team, isArchived, onToggleArchive, isDisabled, save
|
|||||||
hint={defineMessage({id: 'workspace_limits.teams_limit_reached.tool_tip', defaultMessage: 'You\'ve reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams'})}
|
hint={defineMessage({id: 'workspace_limits.teams_limit_reached.tool_tip', defaultMessage: 'You\'ve reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams'})}
|
||||||
placement='bottom'
|
placement='bottom'
|
||||||
>
|
>
|
||||||
{/* OverlayTrigger doesn't play nicely with `disabled` buttons, because the :hover events don't fire. This is a workaround to ensure the popover appears see: https://github.com/react-bootstrap/react-bootstrap/issues/1588*/}
|
|
||||||
<div
|
<div
|
||||||
className={'disabled-overlay-wrapper'}
|
className={'disabled-overlay-wrapper'}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import type {LinkInfo} from '../types';
|
|||||||
|
|
||||||
import './file_preview_modal_main_actions.scss';
|
import './file_preview_modal_main_actions.scss';
|
||||||
|
|
||||||
|
const COPIED_TOOLTIP_DURATION = 2000;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
usedInside?: 'Header' | 'Footer';
|
usedInside?: 'Header' | 'Footer';
|
||||||
showOnlyClose?: boolean;
|
showOnlyClose?: boolean;
|
||||||
@@ -52,6 +54,15 @@ const FilePreviewModalMainActions: React.FC<Props> = (props: Props) => {
|
|||||||
dispatch(getFilePublicLink(props.fileInfo.id));
|
dispatch(getFilePublicLink(props.fileInfo.id));
|
||||||
}
|
}
|
||||||
}, [props.fileInfo, props.enablePublicLink]);
|
}, [props.fileInfo, props.enablePublicLink]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (publicLinkCopied) {
|
||||||
|
setTimeout(() => {
|
||||||
|
setPublicLinkCopied(false);
|
||||||
|
}, COPIED_TOOLTIP_DURATION);
|
||||||
|
}
|
||||||
|
}, [publicLinkCopied]);
|
||||||
|
|
||||||
const copyPublicLink = () => {
|
const copyPublicLink = () => {
|
||||||
copyToClipboard(selectedFilePublicLink ?? '');
|
copyToClipboard(selectedFilePublicLink ?? '');
|
||||||
setPublicLinkCopied(true);
|
setPublicLinkCopied(true);
|
||||||
@@ -96,8 +107,6 @@ const FilePreviewModalMainActions: React.FC<Props> = (props: Props) => {
|
|||||||
key='filePreviewPublicLink'
|
key='filePreviewPublicLink'
|
||||||
placement={tooltipPlacement}
|
placement={tooltipPlacement}
|
||||||
title={publicTooltipMessage}
|
title={publicTooltipMessage}
|
||||||
shouldUpdatePosition={true}
|
|
||||||
onExit={() => setPublicLinkCopied(false)}
|
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href='#'
|
href='#'
|
||||||
|
|||||||
@@ -17,12 +17,6 @@ type State = {
|
|||||||
reactedClass: 'Reaction--reacted' | 'Reaction--reacting' | 'Reaction--unreacted' | 'Reaction--unreacting';
|
reactedClass: 'Reaction--reacted' | 'Reaction--reacting' | 'Reaction--unreacted' | 'Reaction--unreacting';
|
||||||
};
|
};
|
||||||
|
|
||||||
declare module 'react-bootstrap/lib/OverlayTrigger' {
|
|
||||||
interface OverlayTriggerProps {
|
|
||||||
shouldUpdatePosition?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,265 +1,267 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`components/Toast should match snapshot for hiding toast 1`] = `
|
exports[`components/Toast should match snapshot for hiding toast 1`] = `
|
||||||
<div
|
<div>
|
||||||
className="toast"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="toast__message toast__pointer"
|
class="toast"
|
||||||
onClick={[MockFunction]}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="toast__jump"
|
class="toast__message toast__pointer"
|
||||||
>
|
>
|
||||||
<UnreadBelowIcon />
|
<div
|
||||||
Jump to recents
|
class="toast__jump"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<svg
|
||||||
|
aria-label="Down Arrow Icon"
|
||||||
|
height="16"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
width="16"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8.696 2H7.184V11L3.062 6.878L2 7.94L7.94 13.88L13.88 7.94L12.818 6.878L8.696 11V2Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
Jump to recents
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
child
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span>
|
|
||||||
child
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<OverlayTrigger
|
|
||||||
defaultOverlayShown={false}
|
|
||||||
delayShow={400}
|
|
||||||
overlay={<div />}
|
|
||||||
placement="bottom"
|
|
||||||
trigger={
|
|
||||||
Array [
|
|
||||||
"hover",
|
|
||||||
"focus",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="toast__dismiss"
|
class="toast__dismiss"
|
||||||
data-testid="dismissToast"
|
data-testid="dismissToast"
|
||||||
onClick={[Function]}
|
|
||||||
>
|
>
|
||||||
<CloseIcon
|
<span
|
||||||
className="close-btn"
|
class="close-btn"
|
||||||
id="dismissToast"
|
id="dismissToast"
|
||||||
/>
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="Close Icon"
|
||||||
|
height="24px"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18 7.209L16.791 6 12 10.791 7.209 6 6 7.209 10.791 12 6 16.791 7.209 18 12 13.209 16.791 18 18 16.791 13.209 12z"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`components/Toast should match snapshot for showing toast 1`] = `
|
exports[`components/Toast should match snapshot for showing toast 1`] = `
|
||||||
<div
|
<div>
|
||||||
className="toast toast__visible"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="toast__message toast__pointer"
|
class="toast toast__visible"
|
||||||
onClick={[MockFunction]}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="toast__jump"
|
class="toast__message toast__pointer"
|
||||||
>
|
>
|
||||||
<UnreadBelowIcon />
|
<div
|
||||||
Jump to recents
|
class="toast__jump"
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
child
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<OverlayTrigger
|
|
||||||
defaultOverlayShown={false}
|
|
||||||
delayShow={400}
|
|
||||||
overlay={
|
|
||||||
<Tooltip
|
|
||||||
id="toast-close__tooltip"
|
|
||||||
>
|
>
|
||||||
<Memo(MemoizedFormattedMessage)
|
<span>
|
||||||
defaultMessage="Close"
|
<svg
|
||||||
id="general_button.close"
|
aria-label="Down Arrow Icon"
|
||||||
/>
|
height="16"
|
||||||
<div
|
role="img"
|
||||||
className="tooltip__shortcut--txt"
|
viewBox="0 0 16 16"
|
||||||
>
|
width="16"
|
||||||
<Memo(MemoizedFormattedMessage)
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
defaultMessage="esc"
|
>
|
||||||
id="general_button.esc"
|
<path
|
||||||
/>
|
d="M8.696 2H7.184V11L3.062 6.878L2 7.94L7.94 13.88L13.88 7.94L12.818 6.878L8.696 11V2Z"
|
||||||
</div>
|
/>
|
||||||
</Tooltip>
|
</svg>
|
||||||
}
|
</span>
|
||||||
placement="bottom"
|
Jump to recents
|
||||||
trigger={
|
</div>
|
||||||
Array [
|
<span>
|
||||||
"hover",
|
child
|
||||||
"focus",
|
</span>
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="toast__dismiss"
|
|
||||||
data-testid="dismissToast"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<CloseIcon
|
|
||||||
className="close-btn"
|
|
||||||
id="dismissToast"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
<div
|
||||||
|
class="toast__dismiss"
|
||||||
|
data-testid="dismissToast"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="close-btn"
|
||||||
|
id="dismissToast"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="Close Icon"
|
||||||
|
height="24px"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18 7.209L16.791 6 12 10.791 7.209 6 6 7.209 10.791 12 6 16.791 7.209 18 12 13.209 16.791 18 18 16.791 13.209 12z"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`components/Toast should match snapshot for toast width less than 780px 1`] = `
|
exports[`components/Toast should match snapshot for toast width less than 780px 1`] = `
|
||||||
<div
|
<div>
|
||||||
className="toast toast__visible"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="toast__message toast__pointer"
|
class="toast toast__visible"
|
||||||
onClick={[MockFunction]}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="toast__jump"
|
class="toast__message toast__pointer"
|
||||||
>
|
>
|
||||||
<UnreadBelowIcon />
|
<div
|
||||||
Jump to recents
|
class="toast__jump"
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
child
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<OverlayTrigger
|
|
||||||
defaultOverlayShown={false}
|
|
||||||
delayShow={400}
|
|
||||||
overlay={
|
|
||||||
<Tooltip
|
|
||||||
id="toast-close__tooltip"
|
|
||||||
>
|
>
|
||||||
<Memo(MemoizedFormattedMessage)
|
<span>
|
||||||
defaultMessage="Close"
|
<svg
|
||||||
id="general_button.close"
|
aria-label="Down Arrow Icon"
|
||||||
/>
|
height="16"
|
||||||
<div
|
role="img"
|
||||||
className="tooltip__shortcut--txt"
|
viewBox="0 0 16 16"
|
||||||
>
|
width="16"
|
||||||
<Memo(MemoizedFormattedMessage)
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
defaultMessage="esc"
|
>
|
||||||
id="general_button.esc"
|
<path
|
||||||
/>
|
d="M8.696 2H7.184V11L3.062 6.878L2 7.94L7.94 13.88L13.88 7.94L12.818 6.878L8.696 11V2Z"
|
||||||
</div>
|
/>
|
||||||
</Tooltip>
|
</svg>
|
||||||
}
|
</span>
|
||||||
placement="bottom"
|
Jump to recents
|
||||||
trigger={
|
</div>
|
||||||
Array [
|
<span>
|
||||||
"hover",
|
child
|
||||||
"focus",
|
</span>
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="toast__dismiss"
|
|
||||||
data-testid="dismissToast"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<CloseIcon
|
|
||||||
className="close-btn"
|
|
||||||
id="dismissToast"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
<div
|
||||||
|
class="toast__dismiss"
|
||||||
|
data-testid="dismissToast"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="close-btn"
|
||||||
|
id="dismissToast"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="Close Icon"
|
||||||
|
height="24px"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18 7.209L16.791 6 12 10.791 7.209 6 6 7.209 10.791 12 6 16.791 7.209 18 12 13.209 16.791 18 18 16.791 13.209 12z"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`components/Toast should match snapshot to have extraClasses 1`] = `
|
exports[`components/Toast should match snapshot to have extraClasses 1`] = `
|
||||||
<div
|
<div>
|
||||||
className="toast extraClasses toast__visible"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="toast__message toast__pointer"
|
class="toast toast__visible extraClasses"
|
||||||
onClick={[MockFunction]}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="toast__jump"
|
class="toast__message toast__pointer"
|
||||||
>
|
>
|
||||||
<UnreadBelowIcon />
|
<div
|
||||||
Jump to recents
|
class="toast__jump"
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
child
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<OverlayTrigger
|
|
||||||
defaultOverlayShown={false}
|
|
||||||
delayShow={400}
|
|
||||||
overlay={
|
|
||||||
<Tooltip
|
|
||||||
id="toast-close__tooltip"
|
|
||||||
>
|
>
|
||||||
<Memo(MemoizedFormattedMessage)
|
<span>
|
||||||
defaultMessage="Close"
|
<svg
|
||||||
id="general_button.close"
|
aria-label="Down Arrow Icon"
|
||||||
/>
|
height="16"
|
||||||
<div
|
role="img"
|
||||||
className="tooltip__shortcut--txt"
|
viewBox="0 0 16 16"
|
||||||
>
|
width="16"
|
||||||
<Memo(MemoizedFormattedMessage)
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
defaultMessage="esc"
|
>
|
||||||
id="general_button.esc"
|
<path
|
||||||
/>
|
d="M8.696 2H7.184V11L3.062 6.878L2 7.94L7.94 13.88L13.88 7.94L12.818 6.878L8.696 11V2Z"
|
||||||
</div>
|
/>
|
||||||
</Tooltip>
|
</svg>
|
||||||
}
|
</span>
|
||||||
placement="bottom"
|
Jump to recents
|
||||||
trigger={
|
</div>
|
||||||
Array [
|
<span>
|
||||||
"hover",
|
child
|
||||||
"focus",
|
</span>
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="toast__dismiss"
|
|
||||||
data-testid="dismissToast-extraClasses"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<CloseIcon
|
|
||||||
className="close-btn"
|
|
||||||
id="dismissToast"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
<div
|
||||||
|
class="toast__dismiss"
|
||||||
|
data-testid="dismissToast-extraClasses"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="close-btn"
|
||||||
|
id="dismissToast"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="Close Icon"
|
||||||
|
height="24px"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18 7.209L16.791 6 12 10.791 7.209 6 6 7.209 10.791 12 6 16.791 7.209 18 12 13.209 16.791 18 18 16.791 13.209 12z"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`components/Toast should match snapshot to not have actions 1`] = `
|
exports[`components/Toast should match snapshot to not have actions 1`] = `
|
||||||
<div
|
<div>
|
||||||
className="toast toast__visible"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="toast__message"
|
class="toast toast__visible"
|
||||||
>
|
|
||||||
<span>
|
|
||||||
child
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<OverlayTrigger
|
|
||||||
defaultOverlayShown={false}
|
|
||||||
delayShow={400}
|
|
||||||
overlay={<div />}
|
|
||||||
placement="bottom"
|
|
||||||
trigger={
|
|
||||||
Array [
|
|
||||||
"hover",
|
|
||||||
"focus",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="toast__dismiss"
|
class="toast__message"
|
||||||
data-testid="dismissToast"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
>
|
||||||
<CloseIcon
|
<span>
|
||||||
className="close-btn"
|
child
|
||||||
id="dismissToast"
|
</span>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
<div
|
||||||
|
class="toast__dismiss"
|
||||||
|
data-testid="dismissToast"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="close-btn"
|
||||||
|
id="dismissToast"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="Close Icon"
|
||||||
|
height="24px"
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18 7.209L16.791 6 12 10.791 7.209 6 6 7.209 10.791 12 6 16.791 7.209 18 12 13.209 16.791 18 18 16.791 13.209 12z"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {shallow} from 'enzyme';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
import {renderWithContext, screen} from 'tests/react_testing_utils';
|
import {renderWithContext, screen} from 'tests/react_testing_utils';
|
||||||
import * as Utils from 'utils/utils';
|
|
||||||
|
|
||||||
import Toast from './toast';
|
import Toast from './toast';
|
||||||
import type {Props} from './toast';
|
import type {Props} from './toast';
|
||||||
@@ -15,30 +14,34 @@ describe('components/Toast', () => {
|
|||||||
onClick: jest.fn(),
|
onClick: jest.fn(),
|
||||||
show: true,
|
show: true,
|
||||||
showActions: true,
|
showActions: true,
|
||||||
onClickMessage: Utils.localizeMessage('postlist.toast.scrollToBottom', 'Jump to recents'),
|
onClickMessage: (
|
||||||
|
<FormattedMessage
|
||||||
|
id='postlist.toast.scrollToBottom'
|
||||||
|
defaultMessage='Jump to recents'
|
||||||
|
/>
|
||||||
|
),
|
||||||
width: 1000,
|
width: 1000,
|
||||||
};
|
};
|
||||||
|
|
||||||
test('should match snapshot for showing toast', () => {
|
test('should match snapshot for showing toast', () => {
|
||||||
const wrapper = shallow<Toast>(<Toast {...defaultProps}><span>{'child'}</span></Toast>);
|
const {container} = renderWithContext(<Toast {...defaultProps}><span>{'child'}</span></Toast>);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
|
expect(screen.getByTestId('dismissToast')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should match snapshot for hiding toast', () => {
|
test('should match snapshot for hiding toast', () => {
|
||||||
const wrapper = shallow<Toast>(<Toast {...{...defaultProps, show: false}}><span>{'child'}</span></Toast>);
|
const {container} = renderWithContext(<Toast {...{...defaultProps, show: false}}><span>{'child'}</span></Toast>);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.toast__visible').length).toBe(0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should match snapshot for toast width less than 780px', () => {
|
test('should match snapshot for toast width less than 780px', () => {
|
||||||
const wrapper = shallow<Toast>(<Toast {...{...defaultProps, width: 779}}><span>{'child'}</span></Toast>);
|
const {container} = renderWithContext(<Toast {...{...defaultProps, width: 779}}><span>{'child'}</span></Toast>);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should match snapshot to not have actions', () => {
|
test('should match snapshot to not have actions', () => {
|
||||||
const wrapper = shallow<Toast>(<Toast {...{...defaultProps, showActions: false}}><span>{'child'}</span></Toast>);
|
const {container} = renderWithContext(<Toast {...{...defaultProps, showActions: false}}><span>{'child'}</span></Toast>);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
expect(wrapper.find('.toast__pointer').length).toBe(0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should dismiss', () => {
|
test('should dismiss', () => {
|
||||||
@@ -56,7 +59,7 @@ describe('components/Toast', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should match snapshot to have extraClasses', () => {
|
test('should match snapshot to have extraClasses', () => {
|
||||||
const wrapper = shallow<Toast>(<Toast {...{...defaultProps, extraClasses: 'extraClasses'}}><span>{'child'}</span></Toast>);
|
const {container} = renderWithContext(<Toast {...{...defaultProps, extraClasses: 'extraClasses'}}><span>{'child'}</span></Toast>);
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type {ReactNode, MouseEventHandler} from 'react';
|
import type {ReactNode, MouseEventHandler} from 'react';
|
||||||
import type {OverlayTriggerProps} from 'react-bootstrap';
|
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
import OverlayTrigger from 'components/overlay_trigger';
|
|
||||||
import Tooltip from 'components/tooltip';
|
|
||||||
import CloseIcon from 'components/widgets/icons/close_icon';
|
import CloseIcon from 'components/widgets/icons/close_icon';
|
||||||
import UnreadAboveIcon from 'components/widgets/icons/unread_above_icon';
|
import UnreadAboveIcon from 'components/widgets/icons/unread_above_icon';
|
||||||
import UnreadBelowIcon from 'components/widgets/icons/unread_below_icon';
|
import UnreadBelowIcon from 'components/widgets/icons/unread_below_icon';
|
||||||
|
import WithTooltip from 'components/with_tooltip';
|
||||||
|
|
||||||
import Constants from 'utils/constants';
|
import Constants from 'utils/constants';
|
||||||
|
|
||||||
@@ -18,111 +17,88 @@ import './toast.scss';
|
|||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||||
onClickMessage?: string;
|
onClickMessage?: ReactNode;
|
||||||
onDismiss?: () => void;
|
onDismiss?: () => void;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
show: boolean;
|
show: boolean;
|
||||||
showActions?: boolean; //used for showing jump actions
|
showActions?: boolean; //used for showing jump actions
|
||||||
width: number;
|
width: number;
|
||||||
extraClasses?: string;
|
extraClasses?: string;
|
||||||
overlayPlacement?: OverlayTriggerProps['placement'];
|
overlayPlacement?: string;
|
||||||
jumpDirection?: 'up' | 'down';
|
jumpDirection?: 'up' | 'down';
|
||||||
}
|
};
|
||||||
|
|
||||||
export default class Toast extends React.PureComponent<Props> {
|
export default function Toast({
|
||||||
private mounted!: boolean;
|
onClick,
|
||||||
|
onClickMessage,
|
||||||
static defaultProps = {
|
onDismiss,
|
||||||
overlayPlacement: 'bottom',
|
children,
|
||||||
jumpDirection: 'down',
|
show,
|
||||||
};
|
showActions,
|
||||||
|
width,
|
||||||
componentDidMount() {
|
extraClasses = '',
|
||||||
this.mounted = true;
|
overlayPlacement = 'bottom',
|
||||||
|
jumpDirection = 'down',
|
||||||
|
}: Props) {
|
||||||
|
function handleDismiss() {
|
||||||
|
if (typeof onDismiss === 'function') {
|
||||||
|
onDismiss();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
const toastClass = classNames('toast', {
|
||||||
this.mounted = false;
|
toast__visible: show,
|
||||||
}
|
[extraClasses]: extraClasses.length > 0,
|
||||||
|
});
|
||||||
|
|
||||||
handleDismiss = () => {
|
const toastActionClass = classNames('toast__message', {
|
||||||
if (typeof this.props.onDismiss == 'function') {
|
toast__pointer: showActions,
|
||||||
this.props.onDismiss();
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
let toastClass = 'toast';
|
<div className={toastClass}>
|
||||||
const {show, extraClasses, showActions, width, overlayPlacement, jumpDirection} = this.props;
|
<div
|
||||||
|
className={toastActionClass}
|
||||||
if (extraClasses) {
|
onClick={showActions ? onClick : undefined}
|
||||||
toastClass += ` ${extraClasses}`;
|
>
|
||||||
}
|
{showActions && (
|
||||||
|
<div className='toast__jump'>
|
||||||
if (show) {
|
{jumpDirection === 'down' ? (<UnreadBelowIcon/>) : (<UnreadAboveIcon/>)}
|
||||||
toastClass += ' toast__visible';
|
{width > Constants.MOBILE_SCREEN_WIDTH && onClickMessage}
|
||||||
}
|
|
||||||
|
|
||||||
let toastActionClass = 'toast__message';
|
|
||||||
if (showActions) {
|
|
||||||
toastActionClass += ' toast__pointer';
|
|
||||||
}
|
|
||||||
|
|
||||||
const jumpSection = () => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className='toast__jump'
|
|
||||||
>
|
|
||||||
{jumpDirection === 'down' ? <UnreadBelowIcon/> : <UnreadAboveIcon/>}
|
|
||||||
{width > Constants.MOBILE_SCREEN_WIDTH && this.props.onClickMessage}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let closeTooltip = (<div/>);
|
|
||||||
if (showActions && show) {
|
|
||||||
closeTooltip = (
|
|
||||||
<Tooltip id='toast-close__tooltip'>
|
|
||||||
<FormattedMessage
|
|
||||||
id='general_button.close'
|
|
||||||
defaultMessage='Close'
|
|
||||||
/>
|
|
||||||
<div className='tooltip__shortcut--txt'>
|
|
||||||
<FormattedMessage
|
|
||||||
id='general_button.esc'
|
|
||||||
defaultMessage='esc'
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
)}
|
||||||
);
|
{children}
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={toastClass}>
|
|
||||||
<div
|
|
||||||
className={toastActionClass}
|
|
||||||
onClick={showActions ? this.props.onClick : undefined}
|
|
||||||
>
|
|
||||||
{showActions && jumpSection()}
|
|
||||||
{this.props.children}
|
|
||||||
</div>
|
|
||||||
<OverlayTrigger
|
|
||||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
|
||||||
placement={overlayPlacement}
|
|
||||||
overlay={closeTooltip}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className='toast__dismiss'
|
|
||||||
onClick={this.handleDismiss}
|
|
||||||
data-testid={extraClasses ? `dismissToast-${extraClasses}` : 'dismissToast'}
|
|
||||||
>
|
|
||||||
<CloseIcon
|
|
||||||
className='close-btn'
|
|
||||||
id='dismissToast'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</OverlayTrigger>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
<WithTooltip
|
||||||
}
|
id='toast-close__tooltip'
|
||||||
|
placement={overlayPlacement}
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
id='general_button.close'
|
||||||
|
defaultMessage='Close'
|
||||||
|
/>
|
||||||
|
<div className='tooltip__shortcut--txt'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='general_button.esc'
|
||||||
|
defaultMessage='esc'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
disabled={!showActions || !show}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className='toast__dismiss'
|
||||||
|
onClick={handleDismiss}
|
||||||
|
data-testid={extraClasses ? `dismissToast-${extraClasses}` : 'dismissToast'}
|
||||||
|
>
|
||||||
|
<CloseIcon
|
||||||
|
className='close-btn'
|
||||||
|
id='dismissToast'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</WithTooltip>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -393,7 +393,12 @@ export class ToastWrapperClass extends React.PureComponent<Props, State> {
|
|||||||
width,
|
width,
|
||||||
onDismiss: this.hideUnreadToast,
|
onDismiss: this.hideUnreadToast,
|
||||||
onClick: this.scrollToLatestMessages,
|
onClick: this.scrollToLatestMessages,
|
||||||
onClickMessage: localizeMessage('postlist.toast.scrollToBottom', 'Jump to recents'),
|
onClickMessage: (
|
||||||
|
<FormattedMessage
|
||||||
|
id='postlist.toast.scrollToBottom'
|
||||||
|
defaultMessage='Jump to recents'
|
||||||
|
/>
|
||||||
|
),
|
||||||
showActions: !atLatestPost || (atLatestPost && (atBottom === false)),
|
showActions: !atLatestPost || (atLatestPost && (atBottom === false)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -410,7 +415,12 @@ export class ToastWrapperClass extends React.PureComponent<Props, State> {
|
|||||||
width,
|
width,
|
||||||
onDismiss: this.hideUnreadWithBottomStartToast,
|
onDismiss: this.hideUnreadWithBottomStartToast,
|
||||||
onClick: this.scrollToUnreadMessages,
|
onClick: this.scrollToUnreadMessages,
|
||||||
onClickMessage: localizeMessage('postlist.toast.scrollToUnread', 'Jump to unreads'),
|
onClickMessage: (
|
||||||
|
<FormattedMessage
|
||||||
|
id='postlist.toast.scrollToUnread'
|
||||||
|
defaultMessage='Jump to unreads'
|
||||||
|
/>
|
||||||
|
),
|
||||||
showActions: true,
|
showActions: true,
|
||||||
jumpDirection: 'up' as const,
|
jumpDirection: 'up' as const,
|
||||||
};
|
};
|
||||||
@@ -427,7 +437,12 @@ export class ToastWrapperClass extends React.PureComponent<Props, State> {
|
|||||||
const showNewMessagesToastOverrides = {
|
const showNewMessagesToastOverrides = {
|
||||||
onDismiss: this.hideNewMessagesToast,
|
onDismiss: this.hideNewMessagesToast,
|
||||||
onClick: this.scrollToNewMessage,
|
onClick: this.scrollToNewMessage,
|
||||||
onClickMessage: localizeMessage('postlist.toast.scrollToLatest', 'Jump to new messages'),
|
onClickMessage: (
|
||||||
|
<FormattedMessage
|
||||||
|
id='postlist.toast.scrollToLatest'
|
||||||
|
defaultMessage='Jump to new messages'
|
||||||
|
/>
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,5 +3,4 @@
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
default,
|
default,
|
||||||
useSynchronizedImmediate,
|
|
||||||
} from './simple_tooltip';
|
} from './simple_tooltip';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import React, {useState, useMemo} from 'react';
|
import React from 'react';
|
||||||
import type {ReactNode, ComponentProps, CSSProperties} from 'react';
|
import type {ReactNode, ComponentProps, CSSProperties} from 'react';
|
||||||
|
|
||||||
import OverlayTrigger from 'components/overlay_trigger';
|
import OverlayTrigger from 'components/overlay_trigger';
|
||||||
@@ -48,16 +48,3 @@ const SimpleTooltip = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default SimpleTooltip;
|
export default SimpleTooltip;
|
||||||
|
|
||||||
export function useSynchronizedImmediate(): [Partial<ComponentProps<typeof SimpleTooltip>>, (isImmediate: boolean) => void] {
|
|
||||||
const [isImmediate, setImmediate] = useState(false);
|
|
||||||
|
|
||||||
return [
|
|
||||||
useMemo((): Partial<ComponentProps<typeof SimpleTooltip>> => ({
|
|
||||||
onEntered: () => setImmediate(true),
|
|
||||||
animation: !isImmediate,
|
|
||||||
delayShow: isImmediate ? 0 : undefined,
|
|
||||||
}), [isImmediate, setImmediate]),
|
|
||||||
setImmediate,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ export type CommonTooltipProps = {
|
|||||||
shortcut?: ShortcutDefinition;
|
shortcut?: ShortcutDefinition;
|
||||||
emoji?: string;
|
emoji?: string;
|
||||||
emojiStyle?: EmojiStyle;
|
emojiStyle?: EmojiStyle;
|
||||||
shouldUpdatePosition?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTooltip(commonTooltipProps: CommonTooltipProps) {
|
export function createTooltip(commonTooltipProps: CommonTooltipProps) {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ type WithTooltipProps = {
|
|||||||
placement: OverlayTriggerProps['placement'];
|
placement: OverlayTriggerProps['placement'];
|
||||||
onShow?: () => void;
|
onShow?: () => void;
|
||||||
delayHide?: number;
|
delayHide?: number;
|
||||||
onExit?: () => void;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
} & CommonTooltipProps;
|
} & CommonTooltipProps;
|
||||||
const WithTooltip = ({
|
const WithTooltip = ({
|
||||||
@@ -32,8 +31,6 @@ const WithTooltip = ({
|
|||||||
onShow,
|
onShow,
|
||||||
delayHide,
|
delayHide,
|
||||||
children,
|
children,
|
||||||
onExit,
|
|
||||||
shouldUpdatePosition,
|
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}: WithTooltipProps) => {
|
}: WithTooltipProps) => {
|
||||||
const ThisTooltip = useMemo(() => createTooltip({
|
const ThisTooltip = useMemo(() => createTooltip({
|
||||||
@@ -52,8 +49,6 @@ const WithTooltip = ({
|
|||||||
placement={placement}
|
placement={placement}
|
||||||
onEnter={onShow}
|
onEnter={onShow}
|
||||||
delayHide={delayHide}
|
delayHide={delayHide}
|
||||||
onExit={onExit}
|
|
||||||
shouldUpdatePosition={shouldUpdatePosition}
|
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
21
webapp/channels/src/types/external/react-bootstrap.d.ts
поставляемый
21
webapp/channels/src/types/external/react-bootstrap.d.ts
поставляемый
@@ -1,21 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
// Here we are extending the Interface defined by @types/react-bootstrap to include out own
|
|
||||||
// additional types, this soon will be not needed when we upgrade React-Bootstrap version to latest
|
|
||||||
// Until that happens this is the fix
|
|
||||||
|
|
||||||
import * as React from 'react';
|
|
||||||
import type {OverlayTriggerProps} from 'react-bootstrap';
|
|
||||||
|
|
||||||
export interface AdditionalOverlayTriggerProps extends React.ComponentPropsWithRef<typeof OverlayTriggerProps> {
|
|
||||||
|
|
||||||
className?: string;
|
|
||||||
overlay: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare class OverlayTrigger extends React.Component<AdditionalOverlayTriggerProps> {}
|
|
||||||
|
|
||||||
declare module 'react-bootstrap' {
|
|
||||||
export {OverlayTrigger};
|
|
||||||
}
|
|
||||||
Ссылка в новой задаче
Block a user