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>
Этот коммит содержится в:
Bruno
2024-08-23 16:38:03 +05:00
коммит произвёл GitHub
родитель 9a521e83b9
Коммит 1d8ce403c3
3 изменённых файлов: 50 добавлений и 74 удалений

Просмотреть файл

@@ -20,7 +20,6 @@ exports[`components/TextDismissableBar should match snapshot 1`] = `
/> />
</React.Fragment> </React.Fragment>
} }
onDismissal={[MockFunction]}
showCloseButton={true} showCloseButton={true}
/> />
`; `;
@@ -45,7 +44,6 @@ exports[`components/TextDismissableBar should match snapshot, with an internal a
/> />
</React.Fragment> </React.Fragment>
} }
onDismissal={[MockFunction]}
showCloseButton={true} showCloseButton={true}
siteURL="http://testurl.com" siteURL="http://testurl.com"
/> />
@@ -71,7 +69,6 @@ exports[`components/TextDismissableBar should match snapshot, with an internal u
/> />
</React.Fragment> </React.Fragment>
} }
onDismissal={[MockFunction]}
showCloseButton={true} showCloseButton={true}
siteURL="http://testurl.com" siteURL="http://testurl.com"
/> />
@@ -97,7 +94,6 @@ exports[`components/TextDismissableBar should match snapshot, with ean external
/> />
</React.Fragment> </React.Fragment>
} }
onDismissal={[MockFunction]}
showCloseButton={true} showCloseButton={true}
siteURL="http://testurl.com" siteURL="http://testurl.com"
/> />
@@ -123,7 +119,6 @@ exports[`components/TextDismissableBar should match snapshot, with link but with
/> />
</React.Fragment> </React.Fragment>
} }
onDismissal={[MockFunction]}
showCloseButton={true} showCloseButton={true}
/> />
`; `;

Просмотреть файл

@@ -16,45 +16,35 @@ describe('components/TextDismissableBar', () => {
test('should match snapshot', () => { test('should match snapshot', () => {
const props = baseProps; const props = baseProps;
const wrapper = shallow<TextDismissableBar>( const wrapper = shallow(<TextDismissableBar {...props}/>);
<TextDismissableBar {...props}/>,
);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot, with link but without siteURL', () => { test('should match snapshot, with link but without siteURL', () => {
const props = {...baseProps, text: 'A [link](http://testurl.com/admin_console/)'}; const props = {...baseProps, text: 'A [link](http://testurl.com/admin_console/)'};
const wrapper = shallow<TextDismissableBar>( const wrapper = shallow(<TextDismissableBar {...props}/>);
<TextDismissableBar {...props}/>,
);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot, with an internal url', () => { 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 props = {...baseProps, text: 'A [link](http://testurl.com/admin_console/) with an internal url', siteURL: 'http://testurl.com'};
const wrapper = shallow<TextDismissableBar>( const wrapper = shallow(<TextDismissableBar {...props}/>);
<TextDismissableBar {...props}/>,
);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot, with ean external url', () => { 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 props = {...baseProps, text: 'A [link](http://otherurl.com/admin_console/) with an external url', siteURL: 'http://testurl.com'};
const wrapper = shallow<TextDismissableBar>( const wrapper = shallow(<TextDismissableBar {...props}/>);
<TextDismissableBar {...props}/>,
);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('should match snapshot, with an internal and an external link', () => { 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 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>( const wrapper = shallow(<TextDismissableBar {...props}/>);
<TextDismissableBar {...props}/>,
);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });

Просмотреть файл

@@ -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 from 'react'; import React, {useCallback, useEffect, useState} from 'react';
import {trackEvent} from 'actions/telemetry_actions.jsx'; import {trackEvent} from 'actions/telemetry_actions.jsx';
@@ -20,67 +20,58 @@ interface Props extends Partial<AnnouncementBarProps> {
className?: string; className?: string;
} }
type State = { const options = {
dismissed: boolean; singleline: true,
} mentionHighlight: false,
};
export default class TextDismissableBar extends React.PureComponent<Props, State> { const getDismissed = (text?: React.ReactNode) => localStorage.getItem(localStoragePrefix + text?.toString()) === 'true';
constructor(props: Props) {
super(props);
this.state = { const TextDismissableBar = ({
dismissed: true, allowDismissal,
}; text,
} onDismissal,
...extraProps
}: Props) => {
const [dismissed, setDismissed] = useState<boolean>(() => getDismissed(text));
static getDerivedStateFromProps(props: Props) { useEffect(() => {
const dismissed = localStorage.getItem(localStoragePrefix + props.text?.toString()); setDismissed(getDismissed(text));
return { }, [text]);
dismissed: (dismissed === 'true'),
};
}
handleDismiss = () => { const handleDismiss = useCallback(() => {
if (!this.props.allowDismissal) { if (!allowDismissal) {
return; return;
} }
trackEvent('signup', 'click_dismiss_bar'); trackEvent('signup', 'click_dismiss_bar');
localStorage.setItem(localStoragePrefix + this.props.text?.toString(), 'true'); localStorage.setItem(localStoragePrefix + text?.toString(), 'true');
this.setState({ setDismissed(true);
dismissed: true, onDismissal?.();
}); }, [allowDismissal, onDismissal, text]);
if (this.props.onDismissal) {
this.props.onDismissal();
}
};
render() { if (dismissed) {
if (this.state.dismissed) { return null;
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}
</>
}
/>
);
} }
}
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;