blob: cea45a9f76c036acbae991bf1648a28c130f2491 [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, { useState } from 'react';
import { styled, t } from '@superset-ui/core';
import Modal from 'src/components/Modal';
import cx from 'classnames';
import Button from 'src/components/Button';
import withToasts, { ToastProps } from 'src/messageToasts/enhancers/withToasts';
import SyntaxHighlighterCopy from 'src/views/CRUD/data/components/SyntaxHighlighterCopy';
import { useQueryPreviewState } from 'src/views/CRUD/data/hooks';
import { QueryObject } from 'src/views/CRUD/types';
const QueryTitle = styled.div`
color: ${({ theme }) => theme.colors.secondary.light2};
font-size: ${({ theme }) => theme.typography.sizes.s - 1}px;
margin-bottom: 0;
text-transform: uppercase;
`;
const QueryLabel = styled.div`
color: ${({ theme }) => theme.colors.grayscale.dark2};
font-size: ${({ theme }) => theme.typography.sizes.m - 1}px;
padding: 4px 0 24px 0;
`;
const QueryViewToggle = styled.div`
margin: 0 0 ${({ theme }) => theme.gridUnit * 6}px 0;
`;
const TabButton = styled.div`
display: inline;
font-size: ${({ theme }) => theme.typography.sizes.s}px;
padding: ${({ theme }) => theme.gridUnit * 2}px
${({ theme }) => theme.gridUnit * 4}px;
margin-right: ${({ theme }) => theme.gridUnit * 4}px;
color: ${({ theme }) => theme.colors.secondary.dark1};
&.active,
&:focus,
&:hover {
background: ${({ theme }) => theme.colors.secondary.light4};
border-bottom: none;
border-radius: ${({ theme }) => theme.borderRadius}px;
margin-bottom: ${({ theme }) => theme.gridUnit * 2}px;
}
&:hover:not(.active) {
background: ${({ theme }) => theme.colors.secondary.light5};
}
`;
const StyledModal = styled(Modal)`
.ant-modal-body {
padding: ${({ theme }) => theme.gridUnit * 6}px;
}
pre {
font-size: ${({ theme }) => theme.typography.sizes.xs}px;
font-weight: ${({ theme }) => theme.typography.weights.normal};
line-height: ${({ theme }) => theme.typography.sizes.l}px;
height: 375px;
border: none;
}
`;
interface QueryPreviewModalProps extends ToastProps {
onHide: () => void;
openInSqlLab: (id: number) => any;
queries: QueryObject[];
query: QueryObject;
fetchData: (id: number) => any;
show: boolean;
}
function QueryPreviewModal({
onHide,
openInSqlLab,
queries,
query,
fetchData,
show,
addDangerToast,
addSuccessToast,
}: QueryPreviewModalProps) {
const {
handleKeyPress,
handleDataChange,
disablePrevious,
disableNext,
} = useQueryPreviewState<QueryObject>({
queries,
currentQueryId: query.id,
fetchData,
});
const [currentTab, setCurrentTab] = useState<'user' | 'executed'>('user');
const { id, sql, executed_sql } = query;
return (
<div role="none" onKeyUp={handleKeyPress}>
<StyledModal
onHide={onHide}
show={show}
title={t('Query preview')}
footer={[
<Button
data-test="previous-query"
key="previous-query"
disabled={disablePrevious}
onClick={() => handleDataChange(true)}
>
{t('Previous')}
</Button>,
<Button
data-test="next-query"
key="next-query"
disabled={disableNext}
onClick={() => handleDataChange(false)}
>
{t('Next')}
</Button>,
<Button
data-test="open-in-sql-lab"
key="open-in-sql-lab"
buttonStyle="primary"
onClick={() => openInSqlLab(id)}
>
{t('Open in SQL Lab')}
</Button>,
]}
>
<QueryTitle>{t('Tab name')}</QueryTitle>
<QueryLabel>{query.tab_name}</QueryLabel>
<QueryViewToggle>
<TabButton
role="button"
data-test="toggle-user-sql"
className={cx({ active: currentTab === 'user' })}
onClick={() => setCurrentTab('user')}
>
{t('User query')}
</TabButton>
<TabButton
role="button"
data-test="toggle-executed-sql"
className={cx({ active: currentTab === 'executed' })}
onClick={() => setCurrentTab('executed')}
>
{t('Executed query')}
</TabButton>
</QueryViewToggle>
<SyntaxHighlighterCopy
addDangerToast={addDangerToast}
addSuccessToast={addSuccessToast}
language="sql"
>
{(currentTab === 'user' ? sql : executed_sql) || ''}
</SyntaxHighlighterCopy>
</StyledModal>
</div>
);
}
export default withToasts(QueryPreviewModal);