DocSpace-client/packages/asc-web-components/modal-dialog/index.js
AlexeySafronov febf172875 Merge branch 'master' into hotfix/v1.1.1
# Conflicts:
#	lerna.json
#	packages/asc-web-common/package.json
#	packages/asc-web-components/avatar-editor/index.js
#	packages/asc-web-components/avatar-editor/sub-components/avatar-editor-body.js
#	packages/asc-web-components/main-button/index.js
#	packages/asc-web-components/package.json
#	packages/browserslist-config-asc/package.json
#	packages/debug-info/package.json
#	products/ASC.CRM/Client/package.json
#	products/ASC.Calendar/Client/package.json
#	products/ASC.Files/Client/package.json
#	products/ASC.Files/Client/src/HOCs/withFileActions.js
#	products/ASC.Files/Client/src/components/dialogs/DeleteDialog/index.js
#	products/ASC.Files/Client/src/components/panels/SelectFileDialog/AsideView.js
#	products/ASC.Files/Server/DocStore
#	products/ASC.Mail/Client/package.json
#	products/ASC.People/Client/package.json
#	products/ASC.People/Client/src/pages/ProfileAction/Section/Body/updateUserForm.js
#	products/ASC.Projects/Client/package.json
#	web/ASC.Web.Client/package.json
#	web/ASC.Web.Editor/package.json
#	web/ASC.Web.Editor/src/Editor.jsx
#	web/ASC.Web.Login/package.json
2021-12-28 13:35:02 +03:00

276 lines
7.4 KiB
JavaScript

import React from "react";
import PropTypes from "prop-types";
import Backdrop from "../backdrop";
import Aside from "../aside";
import Heading from "../heading";
import { getModalType } from "../utils/device";
import throttle from "lodash/throttle";
import Box from "../box";
import {
CloseButton,
StyledHeader,
Content,
Dialog,
BodyBox,
} from "./styled-modal-dialog";
import Portal from "../portal";
import Loaders from "@appserver/common/components/Loaders";
function Header() {
return null;
}
Header.displayName = "DialogHeader";
function Body() {
return null;
}
Body.displayName = "DialogBody";
function Footer() {
return null;
}
Footer.displayName = "DialogFooter";
class ModalDialog extends React.Component {
static Header = Header;
static Body = Body;
constructor(props) {
super(props);
this.state = { displayType: this.getTypeByWidth() };
this.getTypeByWidth = this.getTypeByWidth.bind(this);
this.resize = this.resize.bind(this);
this.popstate = this.popstate.bind(this);
this.throttledResize = throttle(this.resize, 300);
}
getTypeByWidth() {
if (this.props.displayType !== "auto") return this.props.displayType;
return getModalType();
}
resize() {
if (this.props.displayType !== "auto") return;
const type = this.getTypeByWidth();
if (type === this.state.displayType) return;
this.setState({ displayType: type });
this.props.onResize && this.props.onResize(type);
}
popstate() {
window.removeEventListener("popstate", this.popstate, false);
this.props.onClose();
window.history.go(1);
}
componentDidUpdate(prevProps) {
if (this.props.displayType !== prevProps.displayType) {
this.setState({ displayType: this.getTypeByWidth() });
}
if (this.props.visible && this.state.displayType === "aside") {
window.addEventListener("popstate", this.popstate, false);
}
}
componentDidMount() {
window.addEventListener("resize", this.throttledResize);
window.addEventListener("keyup", this.onKeyPress);
}
componentWillUnmount() {
window.removeEventListener("resize", this.throttledResize);
window.removeEventListener("keyup", this.onKeyPress);
}
onKeyPress = (event) => {
if (event.key === "Esc" || event.key === "Escape") {
this.props.onClose();
}
};
render() {
const {
visible,
scale,
onClose,
zIndex,
asideBodyPadding,
modalBodyPadding,
contentHeight,
contentWidth,
className,
id,
style,
children,
isLoading,
contentPaddingBottom,
removeScroll,
modalLoaderBodyHeight,
} = this.props;
let header = null;
let body = null;
let footer = null;
React.Children.forEach(children, (child) => {
const childType =
child && child.type && (child.type.displayName || child.type.name);
switch (childType) {
case Header.displayName:
header = child;
break;
case Body.displayName:
body = child;
break;
case Footer.displayName:
footer = child;
break;
default:
break;
}
});
const renderModal = () => {
return this.state.displayType === "modal" ? (
<Backdrop
visible={visible}
zIndex={zIndex}
withBackground={true}
isModalDialog
>
<Dialog
className={`${className} not-selectable`}
id={id}
style={style}
>
<Content
contentHeight={contentHeight}
contentWidth={contentWidth}
displayType={this.state.displayType}
>
{isLoading ? (
<Loaders.DialogLoader bodyHeight={modalLoaderBodyHeight} />
) : (
<>
<StyledHeader>
<Heading className="heading" size="medium" truncate={true}>
{header ? header.props.children : null}
</Heading>
<CloseButton
className="modal-dialog-button_close"
onClick={onClose}
></CloseButton>
</StyledHeader>
<BodyBox paddingProp={modalBodyPadding}>
{body ? body.props.children : null}
</BodyBox>
<Box>{footer ? footer.props.children : null}</Box>
</>
)}
</Content>
</Dialog>
</Backdrop>
) : (
<Box className={className} id={id} style={style}>
<Backdrop
visible={visible}
onClick={onClose}
zIndex={zIndex}
isAside={true}
/>
<Aside
visible={visible}
scale={scale}
zIndex={zIndex}
contentPaddingBottom={contentPaddingBottom}
className="modal-dialog-aside not-selectable"
withoutBodyScroll={removeScroll}
>
<Content
contentHeight={contentHeight}
contentWidth={contentWidth}
removeScroll={removeScroll}
displayType={this.state.displayType}
>
{isLoading ? (
<Loaders.DialogAsideLoader withoutAside />
) : (
<>
<StyledHeader className="modal-dialog-aside-header">
<Heading className="heading" size="medium" truncate={true}>
{header ? header.props.children : null}
</Heading>
{scale ? <CloseButton onClick={onClose}></CloseButton> : ""}
</StyledHeader>
<BodyBox
className="modal-dialog-aside-body"
paddingProp={asideBodyPadding}
removeScroll={removeScroll}
>
{body ? body.props.children : null}
</BodyBox>
<Box className="modal-dialog-aside-footer">
{footer ? footer.props.children : null}
</Box>
</>
)}
</Content>
</Aside>
</Box>
);
};
const modalDialog = renderModal();
return <Portal element={modalDialog} />;
}
}
ModalDialog.propTypes = {
children: PropTypes.any,
/** Display dialog or not */
visible: PropTypes.bool,
/** Display type */
displayType: PropTypes.oneOf(["auto", "modal", "aside"]),
/** Indicates the side panel has scale */
scale: PropTypes.bool,
/** Will be triggered when a close button is clicked */
onClose: PropTypes.func,
onResize: PropTypes.func,
/** CSS z-index */
zIndex: PropTypes.number,
/** CSS padding props for body section */
asideBodyPadding: PropTypes.string,
modalBodyPadding: PropTypes.string,
contentHeight: PropTypes.string,
contentWidth: PropTypes.string,
isLoading: PropTypes.bool,
removeScroll: PropTypes.bool,
className: PropTypes.string,
id: PropTypes.string,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
contentPaddingBottom: PropTypes.string,
modalLoaderBodyHeight: PropTypes.string,
};
ModalDialog.defaultProps = {
displayType: "auto",
zIndex: 310,
asideBodyPadding: "16px 0",
modalBodyPadding: "12px 0",
contentWidth: "100%",
};
ModalDialog.Header = Header;
ModalDialog.Body = Body;
ModalDialog.Footer = Footer;
export default ModalDialog;