blob: 3ab5a9350c7dba33223fb4894f554b7c0532f6bb [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import { isNil } from 'lodash';
import { styled, SupersetThemeProps, t } from '@superset-ui/core';
import { Modal as BaseModal } from 'src/common/components';
import Button from 'src/components/Button';
import { css } from '@emotion/core';
interface ModalProps {
className?: string;
children: React.ReactNode;
disablePrimaryButton?: boolean;
onHide: () => void;
onHandledPrimaryAction?: () => void;
primaryButtonName?: string;
primaryButtonType?: 'primary' | 'danger';
show: boolean;
name?: string;
title: React.ReactNode;
width?: string;
maxWidth?: string;
responsive?: boolean;
hideFooter?: boolean;
centered?: boolean;
footer?: React.ReactNode;
wrapProps?: object;
height?: string;
closable?: boolean;
}
interface StyledModalProps extends SupersetThemeProps {
maxWidth?: string;
responsive?: boolean;
height?: string;
hideFooter?: boolean;
}
export const StyledModal = styled(BaseModal)<StyledModalProps>`
${({ theme, responsive, maxWidth }) =>
responsive &&
css`
max-width: ${maxWidth ?? '900px'};
padding-left: ${theme.gridUnit * 3}px;
padding-right: ${theme.gridUnit * 3}px;
`}
.ant-modal-header {
background-color: ${({ theme }) => theme.colors.grayscale.light4};
border-radius: ${({ theme }) => theme.borderRadius}px
${({ theme }) => theme.borderRadius}px 0 0;
padding-left: ${({ theme }) => theme.gridUnit * 4}px;
padding-right: ${({ theme }) => theme.gridUnit * 4}px;
.ant-modal-title h4 {
display: flex;
margin: 0;
align-items: center;
}
}
.ant-modal-close-x {
display: flex;
align-items: center;
.close {
flex: 1 1 auto;
margin-bottom: ${({ theme }) => theme.gridUnit}px;
color: ${({ theme }) => theme.colors.secondary.dark1};
font-size: 32px;
font-weight: ${({ theme }) => theme.typography.weights.light};
}
}
.ant-modal-body {
padding: ${({ theme }) => theme.gridUnit * 4}px;
overflow: auto;
${({ height }) => height && `height: ${height};`}
}
.ant-modal-footer {
border-top: ${({ theme }) => theme.gridUnit / 4}px solid
${({ theme }) => theme.colors.grayscale.light2};
padding: ${({ theme }) => theme.gridUnit * 4}px;
.btn {
font-size: 12px;
text-transform: uppercase;
}
.btn + .btn {
margin-left: ${({ theme }) => theme.gridUnit * 2}px;
}
}
// styling for Tabs component
// Aaron note 20-11-19: this seems to be exclusively here for the Edit Database modal.
// TODO: remove this as it is a special case.
.ant-tabs-top {
margin-top: -${({ theme }) => theme.gridUnit * 4}px;
}
&.no-content-padding .ant-modal-body {
padding: 0;
}
`;
const CustomModal = ({
children,
disablePrimaryButton = false,
onHide,
onHandledPrimaryAction,
primaryButtonName = t('OK'),
primaryButtonType = 'primary',
show,
name,
title,
width,
maxWidth,
responsive = false,
centered,
footer,
hideFooter,
wrapProps,
...rest
}: ModalProps) => {
const modalFooter = isNil(footer)
? [
<Button key="back" onClick={onHide} cta data-test="modal-cancel-button">
{t('Cancel')}
</Button>,
<Button
key="submit"
buttonStyle={primaryButtonType}
disabled={disablePrimaryButton}
onClick={onHandledPrimaryAction}
cta
data-test="modal-confirm-button"
>
{primaryButtonName}
</Button>,
]
: footer;
const modalWidth = width || (responsive ? '100vw' : '600px');
return (
<StyledModal
centered={!!centered}
onOk={onHandledPrimaryAction}
onCancel={onHide}
width={modalWidth}
maxWidth={maxWidth}
responsive={responsive}
visible={show}
title={title}
closeIcon={
<span className="close" aria-hidden="true">
×
</span>
}
footer={!hideFooter ? modalFooter : null}
wrapProps={{ 'data-test': `${name || title}-modal`, ...wrapProps }}
{...rest}
>
{children}
</StyledModal>
);
};
CustomModal.displayName = 'Modal';
// TODO: in another PR, rename this to CompatabilityModal
// and demote it as the default export.
// We should start using AntD component interfaces going forward.
const Modal = Object.assign(CustomModal, {
error: BaseModal.error,
warning: BaseModal.warning,
confirm: BaseModal.confirm,
useModal: BaseModal.useModal,
});
export default Modal;