refactor(component): convert TextDismissableBar from class to function component (#27955)
* refactor(component): convert TextDismissableBar from class to function component * perf:Code optimized * refactor(component):props vertically formatted, getDismissed function moved outside * Update webapp/channels/src/components/announcement_bar/text_dismissable_bar.tsx Co-authored-by: Daniel Espino García <larkox@gmail.com> * refactor:setDismissed formatted vertically * test(text_dismissable_bar):snapshot test updated * refactor: remove type from shallow rendering in TextDismissableBar test --------- Co-authored-by: Daniel Espino García <larkox@gmail.com> Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
@@ -20,7 +20,6 @@ exports[`components/TextDismissableBar should match snapshot 1`] = `
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
onDismissal={[MockFunction]}
|
||||
showCloseButton={true}
|
||||
/>
|
||||
`;
|
||||
@@ -45,7 +44,6 @@ exports[`components/TextDismissableBar should match snapshot, with an internal a
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
onDismissal={[MockFunction]}
|
||||
showCloseButton={true}
|
||||
siteURL="http://testurl.com"
|
||||
/>
|
||||
@@ -71,7 +69,6 @@ exports[`components/TextDismissableBar should match snapshot, with an internal u
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
onDismissal={[MockFunction]}
|
||||
showCloseButton={true}
|
||||
siteURL="http://testurl.com"
|
||||
/>
|
||||
@@ -97,7 +94,6 @@ exports[`components/TextDismissableBar should match snapshot, with ean external
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
onDismissal={[MockFunction]}
|
||||
showCloseButton={true}
|
||||
siteURL="http://testurl.com"
|
||||
/>
|
||||
@@ -123,7 +119,6 @@ exports[`components/TextDismissableBar should match snapshot, with link but with
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
onDismissal={[MockFunction]}
|
||||
showCloseButton={true}
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -16,45 +16,35 @@ describe('components/TextDismissableBar', () => {
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const props = baseProps;
|
||||
const wrapper = shallow<TextDismissableBar>(
|
||||
<TextDismissableBar {...props}/>,
|
||||
);
|
||||
const wrapper = shallow(<TextDismissableBar {...props}/>);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot, with link but without siteURL', () => {
|
||||
const props = {...baseProps, text: 'A [link](http://testurl.com/admin_console/)'};
|
||||
const wrapper = shallow<TextDismissableBar>(
|
||||
<TextDismissableBar {...props}/>,
|
||||
);
|
||||
const wrapper = shallow(<TextDismissableBar {...props}/>);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot, with an internal url', () => {
|
||||
const props = {...baseProps, text: 'A [link](http://testurl.com/admin_console/) with an internal url', siteURL: 'http://testurl.com'};
|
||||
const wrapper = shallow<TextDismissableBar>(
|
||||
<TextDismissableBar {...props}/>,
|
||||
);
|
||||
const wrapper = shallow(<TextDismissableBar {...props}/>);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot, with ean external url', () => {
|
||||
const props = {...baseProps, text: 'A [link](http://otherurl.com/admin_console/) with an external url', siteURL: 'http://testurl.com'};
|
||||
const wrapper = shallow<TextDismissableBar>(
|
||||
<TextDismissableBar {...props}/>,
|
||||
);
|
||||
const wrapper = shallow(<TextDismissableBar {...props}/>);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot, with an internal and an external link', () => {
|
||||
const props = {...baseProps, text: 'A [link](http://testurl.com/admin_console/) with an internal url and a [link](http://other-url.com/admin_console/) with an external url', siteURL: 'http://testurl.com'};
|
||||
const wrapper = shallow<TextDismissableBar>(
|
||||
<TextDismissableBar {...props}/>,
|
||||
);
|
||||
const wrapper = shallow(<TextDismissableBar {...props}/>);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import React, {useCallback, useEffect, useState} from 'react';
|
||||
|
||||
import {trackEvent} from 'actions/telemetry_actions.jsx';
|
||||
|
||||
@@ -20,67 +20,58 @@ interface Props extends Partial<AnnouncementBarProps> {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
type State = {
|
||||
dismissed: boolean;
|
||||
}
|
||||
const options = {
|
||||
singleline: true,
|
||||
mentionHighlight: false,
|
||||
};
|
||||
|
||||
export default class TextDismissableBar extends React.PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
const getDismissed = (text?: React.ReactNode) => localStorage.getItem(localStoragePrefix + text?.toString()) === 'true';
|
||||
|
||||
this.state = {
|
||||
dismissed: true,
|
||||
};
|
||||
}
|
||||
const TextDismissableBar = ({
|
||||
allowDismissal,
|
||||
text,
|
||||
onDismissal,
|
||||
...extraProps
|
||||
}: Props) => {
|
||||
const [dismissed, setDismissed] = useState<boolean>(() => getDismissed(text));
|
||||
|
||||
static getDerivedStateFromProps(props: Props) {
|
||||
const dismissed = localStorage.getItem(localStoragePrefix + props.text?.toString());
|
||||
return {
|
||||
dismissed: (dismissed === 'true'),
|
||||
};
|
||||
}
|
||||
useEffect(() => {
|
||||
setDismissed(getDismissed(text));
|
||||
}, [text]);
|
||||
|
||||
handleDismiss = () => {
|
||||
if (!this.props.allowDismissal) {
|
||||
const handleDismiss = useCallback(() => {
|
||||
if (!allowDismissal) {
|
||||
return;
|
||||
}
|
||||
trackEvent('signup', 'click_dismiss_bar');
|
||||
|
||||
localStorage.setItem(localStoragePrefix + this.props.text?.toString(), 'true');
|
||||
this.setState({
|
||||
dismissed: true,
|
||||
});
|
||||
if (this.props.onDismissal) {
|
||||
this.props.onDismissal();
|
||||
}
|
||||
};
|
||||
localStorage.setItem(localStoragePrefix + text?.toString(), 'true');
|
||||
setDismissed(true);
|
||||
onDismissal?.();
|
||||
}, [allowDismissal, onDismissal, text]);
|
||||
|
||||
render() {
|
||||
if (this.state.dismissed) {
|
||||
return null;
|
||||
}
|
||||
const {allowDismissal, text, ...extraProps} = this.props;
|
||||
return (
|
||||
<AnnouncementBar
|
||||
{...extraProps}
|
||||
showCloseButton={allowDismissal}
|
||||
handleClose={this.handleDismiss}
|
||||
message={
|
||||
<>
|
||||
<i className='icon icon-information-outline'/>
|
||||
{typeof text === 'string' ? (
|
||||
<Markdown
|
||||
message={text}
|
||||
options={{
|
||||
singleline: true,
|
||||
mentionHighlight: false,
|
||||
}}
|
||||
/>
|
||||
) : text}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
if (dismissed) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<AnnouncementBar
|
||||
{...extraProps}
|
||||
showCloseButton={allowDismissal}
|
||||
handleClose={handleDismiss}
|
||||
message={
|
||||
<>
|
||||
<i className='icon icon-information-outline'/>
|
||||
{typeof text === 'string' ? (
|
||||
<Markdown
|
||||
message={text}
|
||||
options={options}
|
||||
/>
|
||||
) : text}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextDismissableBar;
|
||||
|
||||
Ссылка в новой задаче
Block a user