MM-63911 Fix link copied behavior and style in get link modal (#30854)
* changed copy link behavior to match behavior elsewhere * update timing, fix linting issues, fix style in modal header * updated test * updated test and snapshot * fix linting error * Fix snapshots --------- Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f09df430b9
Коммит
a001367d43
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 67 KiB После Ширина: | Высота: | Размер: 63 KiB |
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 106 KiB После Ширина: | Высота: | Размер: 106 KiB |
Двоичный файл не отображается.
|
До Ширина: | Высота: | Размер: 66 KiB После Ширина: | Высота: | Размер: 62 KiB |
@@ -36,11 +36,11 @@ exports[`components/GetLinkModal should have called onHide 1`] = `
|
||||
closeLabel="Close"
|
||||
id="getLinkModalLabel"
|
||||
>
|
||||
<h4
|
||||
<h2
|
||||
className="modal-title"
|
||||
>
|
||||
title
|
||||
</h4>
|
||||
</h2>
|
||||
</ModalHeader>
|
||||
<ModalBody
|
||||
bsClass="modal-body"
|
||||
@@ -71,26 +71,20 @@ exports[`components/GetLinkModal should have called onHide 1`] = `
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary pull-left"
|
||||
className="btn btn-primary btn-success pull-left"
|
||||
data-copy-btn="true"
|
||||
id="linkModalCopyLink"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Copy Link"
|
||||
id="get_link.copy"
|
||||
<i
|
||||
className="icon icon-check"
|
||||
/>
|
||||
</button>
|
||||
<p
|
||||
className="alert alert-success alert--confirm"
|
||||
>
|
||||
<SuccessIcon />
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage=" Link copied"
|
||||
defaultMessage="Copied"
|
||||
id="get_link.clipboard"
|
||||
/>
|
||||
</p>
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
`;
|
||||
@@ -131,11 +125,11 @@ exports[`components/GetLinkModal should have called onHide 2`] = `
|
||||
closeLabel="Close"
|
||||
id="getLinkModalLabel"
|
||||
>
|
||||
<h4
|
||||
<h2
|
||||
className="modal-title"
|
||||
>
|
||||
title
|
||||
</h4>
|
||||
</h2>
|
||||
</ModalHeader>
|
||||
<ModalBody
|
||||
bsClass="modal-body"
|
||||
@@ -172,6 +166,9 @@ exports[`components/GetLinkModal should have called onHide 2`] = `
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
className="icon icon-link-variant"
|
||||
/>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Copy Link"
|
||||
id="get_link.copy"
|
||||
@@ -217,11 +214,11 @@ exports[`components/GetLinkModal should match snapshot when all props is set 1`]
|
||||
closeLabel="Close"
|
||||
id="getLinkModalLabel"
|
||||
>
|
||||
<h4
|
||||
<h2
|
||||
className="modal-title"
|
||||
>
|
||||
title
|
||||
</h4>
|
||||
</h2>
|
||||
</ModalHeader>
|
||||
<ModalBody
|
||||
bsClass="modal-body"
|
||||
@@ -263,6 +260,9 @@ exports[`components/GetLinkModal should match snapshot when all props is set 1`]
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
className="icon icon-link-variant"
|
||||
/>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Copy Link"
|
||||
id="get_link.copy"
|
||||
@@ -308,11 +308,11 @@ exports[`components/GetLinkModal should match snapshot when helpText is not set
|
||||
closeLabel="Close"
|
||||
id="getLinkModalLabel"
|
||||
>
|
||||
<h4
|
||||
<h2
|
||||
className="modal-title"
|
||||
>
|
||||
title
|
||||
</h4>
|
||||
</h2>
|
||||
</ModalHeader>
|
||||
<ModalBody
|
||||
bsClass="modal-body"
|
||||
@@ -349,6 +349,9 @@ exports[`components/GetLinkModal should match snapshot when helpText is not set
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
className="icon icon-link-variant"
|
||||
/>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Copy Link"
|
||||
id="get_link.copy"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import {Modal} from 'react-bootstrap';
|
||||
import {act} from 'react-dom/test-utils';
|
||||
|
||||
import GetLinkModal from 'components/get_link_modal';
|
||||
|
||||
@@ -19,6 +20,14 @@ describe('components/GetLinkModal', () => {
|
||||
link: 'https://mattermost.com',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('should match snapshot when all props is set', () => {
|
||||
const helpText = 'help text';
|
||||
const props = {...requiredProps, helpText};
|
||||
@@ -68,4 +77,44 @@ describe('components/GetLinkModal', () => {
|
||||
wrapper.find('#linkModalTextArea').simulate('click');
|
||||
expect(wrapper.state('copiedLink')).toBe(true);
|
||||
});
|
||||
|
||||
test('should change button state when copying', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<GetLinkModal {...requiredProps}/>,
|
||||
);
|
||||
|
||||
// Initial state
|
||||
expect(wrapper.find('#linkModalCopyLink').text()).toContain('Copy Link');
|
||||
expect(wrapper.find('#linkModalCopyLink').hasClass('btn-primary')).toBe(true);
|
||||
expect(wrapper.find('#linkModalCopyLink').hasClass('btn-success')).toBe(false);
|
||||
|
||||
// After copying
|
||||
wrapper.find('#linkModalCopyLink').simulate('click');
|
||||
expect(wrapper.find('#linkModalCopyLink').text()).toContain('Copied');
|
||||
expect(wrapper.find('#linkModalCopyLink').hasClass('btn-primary')).toBe(true);
|
||||
expect(wrapper.find('#linkModalCopyLink').hasClass('btn-success')).toBe(true);
|
||||
|
||||
// After timeout
|
||||
act(() => {
|
||||
jest.advanceTimersByTime(1000);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('#linkModalCopyLink').text()).toContain('Copy Link');
|
||||
expect(wrapper.find('#linkModalCopyLink').hasClass('btn-primary')).toBe(true);
|
||||
expect(wrapper.find('#linkModalCopyLink').hasClass('btn-success')).toBe(false);
|
||||
});
|
||||
|
||||
test('should cleanup timeout on unmount', () => {
|
||||
const wrapper = mountWithIntl(
|
||||
<GetLinkModal {...requiredProps}/>,
|
||||
);
|
||||
|
||||
wrapper.find('#linkModalCopyLink').simulate('click');
|
||||
expect(wrapper.state('copiedLink')).toBe(true);
|
||||
|
||||
wrapper.unmount();
|
||||
jest.advanceTimersByTime(1000);
|
||||
|
||||
// If we get here without errors, the timeout was properly cleaned up
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,8 +5,6 @@ import React from 'react';
|
||||
import {Modal} from 'react-bootstrap';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
import SuccessIcon from 'components/widgets/icons/fa_success_icon';
|
||||
|
||||
type Props = {
|
||||
show: boolean;
|
||||
onHide: () => void;
|
||||
@@ -22,6 +20,7 @@ type State = {
|
||||
|
||||
export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
private textAreaRef = React.createRef<HTMLTextAreaElement>();
|
||||
private resetTimeout: NodeJS.Timeout | null = null;
|
||||
public static defaultProps = {
|
||||
helpText: null,
|
||||
};
|
||||
@@ -33,7 +32,16 @@ export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
public componentWillUnmount(): void {
|
||||
if (this.resetTimeout) {
|
||||
clearTimeout(this.resetTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
public onHide = (): void => {
|
||||
if (this.resetTimeout) {
|
||||
clearTimeout(this.resetTimeout);
|
||||
}
|
||||
this.setState({copiedLink: false});
|
||||
this.props.onHide();
|
||||
};
|
||||
@@ -47,6 +55,12 @@ export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
|
||||
try {
|
||||
this.setState({copiedLink: document.execCommand('copy')});
|
||||
if (this.resetTimeout) {
|
||||
clearTimeout(this.resetTimeout);
|
||||
}
|
||||
this.resetTimeout = setTimeout(() => {
|
||||
this.setState({copiedLink: false});
|
||||
}, 1000);
|
||||
} catch (err) {
|
||||
this.setState({copiedLink: false});
|
||||
}
|
||||
@@ -73,13 +87,26 @@ export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
id='linkModalCopyLink'
|
||||
data-copy-btn='true'
|
||||
type='button'
|
||||
className='btn btn-primary pull-left'
|
||||
className={`btn ${this.state.copiedLink ? 'btn-primary btn-success' : 'btn-primary'} pull-left`}
|
||||
onClick={this.copyLink}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='get_link.copy'
|
||||
defaultMessage='Copy Link'
|
||||
/>
|
||||
{this.state.copiedLink ? (
|
||||
<>
|
||||
<i className='icon icon-check'/>
|
||||
<FormattedMessage
|
||||
id='get_link.clipboard'
|
||||
defaultMessage='Copied'
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className='icon icon-link-variant'/>
|
||||
<FormattedMessage
|
||||
id='get_link.copy'
|
||||
defaultMessage='Copy Link'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -96,19 +123,6 @@ export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
/>
|
||||
);
|
||||
|
||||
let copyLinkConfirm = null;
|
||||
if (this.state.copiedLink) {
|
||||
copyLinkConfirm = (
|
||||
<p className='alert alert-success alert--confirm'>
|
||||
<SuccessIcon/>
|
||||
<FormattedMessage
|
||||
id='get_link.clipboard'
|
||||
defaultMessage=' Link copied'
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
dialogClassName='a11y__modal'
|
||||
@@ -122,7 +136,7 @@ export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
id='getLinkModalLabel'
|
||||
closeButton={true}
|
||||
>
|
||||
<h4 className='modal-title'>{this.props.title}</h4>
|
||||
<h2 className='modal-title'>{this.props.title}</h2>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{helpText}
|
||||
@@ -141,7 +155,6 @@ export default class GetLinkModal extends React.PureComponent<Props, State> {
|
||||
/>
|
||||
</button>
|
||||
{copyLink}
|
||||
{copyLinkConfirm}
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -230,6 +230,19 @@ button {
|
||||
color: rgba(var(--center-channel-color-rgb), 0.32) !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.btn-success {
|
||||
background-color: var(--online-indicator);
|
||||
color: var(--button-color-rgb);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--online-indicator);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--online-indicator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-secondary {
|
||||
|
||||
@@ -328,6 +328,7 @@
|
||||
background: transparent;
|
||||
color: functions.v(center-channel-color);
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user