[MM-57717] Convert SubMenuModal from Class Component to Function Component (#26902)

* Convert SubMenuModal from Class Component to Function Component

* Style fixes

* Review fixes

* Review fix

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
MeHow25
2024-05-06 12:05:06 +02:00
коммит произвёл GitHub
родитель 539daee634
Коммит 204485e541
3 изменённых файлов: 71 добавлений и 65 удалений

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

@@ -33,6 +33,7 @@ exports[`components/submenu_modal should match snapshot 1`] = `
<ModalBody
bsClass="modal-body"
componentClass="div"
data-testid="SubMenuModalBody"
onClick={[Function]}
>
<MenuWrapper

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

@@ -1,10 +1,12 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {fireEvent, waitForElementToBeRemoved} from '@testing-library/react';
import {shallow} from 'enzyme';
import React from 'react';
import {Modal} from 'react-bootstrap';
import {withIntl} from 'tests/helpers/intl-test-helper';
import {render, screen, userEvent} from 'tests/react_testing_utils';
import SubMenuModal from './submenu_modal';
@@ -55,14 +57,20 @@ describe('components/submenu_modal', () => {
expect(wrapper).toMatchSnapshot();
});
test('should match state when onHide is called', () => {
const wrapper = shallow<SubMenuModal>(
test('should hide on modal body click', async () => {
const view = render(withIntl(
<SubMenuModal {...baseProps}/>,
);
));
wrapper.setState({show: true});
wrapper.instance().onHide();
expect(wrapper.state('show')).toEqual(false);
screen.getByText('Text A');
screen.getByText('Text B');
screen.getByText('Text C');
fireEvent.click(view.getByTestId('SubMenuModalBody'));
await waitForElementToBeRemoved(() => screen.getByText('Text A'));
expect(screen.queryAllByText('Text B').length).toBe(0);
expect(screen.queryAllByText('Text C').length).toBe(0);
});
test('should have called click function when button is clicked', async () => {

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

@@ -1,10 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import React, {useCallback, useMemo, useState} from 'react';
import {Modal} from 'react-bootstrap';
import * as Utils from 'utils/utils';
import {useIntl} from 'react-intl';
import Menu from '../../menu';
import type SubMenuItem from '../../menu_items/submenu_item';
@@ -17,63 +16,61 @@ type Props = {
onExited: () => void;
}
type State = {
show: boolean;
}
const SubMenuModal = ({
elements,
onExited,
}: Props) => {
const [show, setShow] = useState(true);
const intl = useIntl();
export default class SubMenuModal extends React.PureComponent<Props, State> {
public constructor(props: Props) {
super(props);
this.state = {
show: true,
};
}
const onHide = useCallback(() => {
setShow(false);
}, []);
public onHide = () => { //public because it is used on tests
this.setState({show: false});
};
public render() {
let SubMenuItems;
if (this.props.elements) {
SubMenuItems = this.props.elements.map((element) => {
return (
<Menu.ItemSubMenu
key={element.id}
id={element.id}
text={element.text}
subMenu={element.subMenu}
action={element.action}
filter={element.filter}
root={false}
/>
);
});
const subMenuItems = useMemo(() => {
if (!elements) {
return undefined;
}
return (
<Modal
dialogClassName={'SubMenuModal a11y__modal mobile-sub-menu'}
show={this.state.show}
onHide={this.onHide}
onExited={this.props.onExited}
enforceFocus={false}
id='submenuModal'
role='dialog'
>
<Modal.Body
onClick={this.onHide}
>
<MenuWrapper>
<Menu
openLeft={true}
ariaLabel={Utils.localizeMessage('post_info.submenu.mobile', 'mobile submenu').toLowerCase()}
>
{SubMenuItems}
</Menu>
<div/>
</MenuWrapper>
</Modal.Body>
</Modal>
return elements.map(
(element) => (
<Menu.ItemSubMenu
key={element.id}
id={element.id}
text={element.text}
subMenu={element.subMenu}
action={element.action}
filter={element.filter}
root={false}
/>),
);
}
}
}, [elements]);
return (
<Modal
dialogClassName={'SubMenuModal a11y__modal mobile-sub-menu'}
show={show}
onHide={onHide}
onExited={onExited}
enforceFocus={false}
id='submenuModal'
role='dialog'
>
<Modal.Body
data-testid={'SubMenuModalBody'}
onClick={onHide}
>
<MenuWrapper>
<Menu
openLeft={true}
ariaLabel={intl.formatMessage({id: 'post_info.submenu.mobile', defaultMessage: 'mobile submenu'})}
>
{subMenuItems}
</Menu>
<div/>
</MenuWrapper>
</Modal.Body>
</Modal>
);
};
export default React.memo(SubMenuModal);