diff --git a/superset-frontend/src/explore/components/controls/CustomCSV.tsx b/superset-frontend/src/explore/components/controls/CustomCSV.tsx new file mode 100644 index 0000000000000..a8ebd975d3344 --- /dev/null +++ b/superset-frontend/src/explore/components/controls/CustomCSV.tsx @@ -0,0 +1,76 @@ +/** + * 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 { styled } from '@superset-ui/core'; +import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/light'; +import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github'; +import CopyToClipboard from 'src/components/CopyToClipboard'; +import { CopyButton } from 'src/explore/components/DataTableControl'; +import markdownSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/markdown'; +import htmlSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/htmlbars'; +import sqlSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql'; +import jsonSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/json'; + +const CopyButtonViewQuery = styled(CopyButton)` + && { + margin: 0 0 ${({ theme }) => theme.gridUnit}px; + } +`; + +SyntaxHighlighter.registerLanguage('markdown', markdownSyntax); +SyntaxHighlighter.registerLanguage('html', htmlSyntax); +SyntaxHighlighter.registerLanguage('sql', sqlSyntax); +SyntaxHighlighter.registerLanguage('json', jsonSyntax); + +interface ViewQueryProps { + sql: string; + language?: string; +} + +const StyledSyntaxContainer = styled.div` + height: 100%; + display: flex; + flex-direction: column; +`; + +const StyledSyntaxHighlighter = styled(SyntaxHighlighter)` + flex: 1; +`; + +const ViewQuery: React.FC = props => { + const { sql, language = 'sql' } = props; + return ( + + + + + } + /> + + {sql} + + + ); +}; + +export default ViewQuery; diff --git a/superset-frontend/src/explore/components/controls/CustomCSVModal.tsx b/superset-frontend/src/explore/components/controls/CustomCSVModal.tsx new file mode 100644 index 0000000000000..023c1e3551307 --- /dev/null +++ b/superset-frontend/src/explore/components/controls/CustomCSVModal.tsx @@ -0,0 +1,92 @@ +/** + * 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, { useEffect, useState } from 'react'; +import { styled, ensureIsArray, t } from '@superset-ui/core'; +import Loading from 'src/components/Loading'; +import { getClientErrorObject } from 'src/utils/getClientErrorObject'; +import { getChartDataRequest } from 'src/components/Chart/chartAction'; +import ViewQuery from 'src/explore/components/controls/ViewQuery'; + +interface Props { + latestQueryFormData: object; +} + +type Result = { + query: string; + language: string; +}; + +const ViewQueryModalContainer = styled.div` + height: 100%; + display: flex; + flex-direction: column; +`; + +const ViewQueryModal: React.FC = props => { + const [result, setResult] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const loadChartData = (resultType: string) => { + setIsLoading(true); + getChartDataRequest({ + formData: props.latestQueryFormData, + resultFormat: 'json', + resultType, + }) + .then(({ json }) => { + setResult(ensureIsArray(json.result)); + setIsLoading(false); + setError(null); + }) + .catch(response => { + getClientErrorObject(response).then(({ error, message }) => { + setError( + error || + message || + response.statusText || + t('Sorry, An error occurred'), + ); + setIsLoading(false); + }); + }); + }; + useEffect(() => { + loadChartData('query'); + }, [JSON.stringify(props.latestQueryFormData)]); + + if (isLoading) { + return ; + } + if (error) { + return
{error}
; + } + + return ( + + {result.map(item => + item.query ? ( + + ) : null, + )} + + ); +}; + +export default ViewQueryModal; diff --git a/superset-frontend/src/explore/components/controls/CustomCSVModalFooter.tsx b/superset-frontend/src/explore/components/controls/CustomCSVModalFooter.tsx new file mode 100644 index 0000000000000..4f4af039b1a23 --- /dev/null +++ b/superset-frontend/src/explore/components/controls/CustomCSVModalFooter.tsx @@ -0,0 +1,83 @@ +/** + * 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 { isObject } from 'lodash'; +import { t, SupersetClient } from '@superset-ui/core'; +import Button from 'src/components/Button'; + +interface SimpleDataSource { + id: string; + sql: string; + type: string; +} + +interface ViewQueryModalFooterProps { + closeModal?: Function; + changeDatasource?: Function; + datasource?: SimpleDataSource; +} + +const CLOSE = t('Close'); +const SAVE_AS_DATASET = t('Save as Dataset'); +const OPEN_IN_SQL_LAB = t('Open in SQL Lab'); + +const ViewQueryModalFooter: React.FC = (props: { + closeModal: () => void; + changeDatasource: () => void; + datasource: SimpleDataSource; +}) => { + const viewInSQLLab = (id: string, type: string, sql: string) => { + const payload = { + datasourceKey: `${id}__${type}`, + sql, + }; + SupersetClient.postForm('/superset/sqllab/', payload); + }; + + const openSQL = () => { + const { datasource } = props; + if (isObject(datasource)) { + const { id, type, sql } = datasource; + viewInSQLLab(id, type, sql); + } + }; + return ( +
+ + + +
+ ); +}; + +export default ViewQueryModalFooter; diff --git a/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx b/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx index e9a00ba66c953..a97a9136f7df0 100644 --- a/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx +++ b/superset-frontend/src/explore/components/useExploreAdditionalActionsMenu/index.jsx @@ -31,6 +31,9 @@ import copyTextToClipboard from 'src/utils/copy'; import HeaderReportDropDown from 'src/components/ReportModal/HeaderReportDropdown'; import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags'; import ViewQueryModal from '../controls/ViewQueryModal'; +/* NGLS - BEGIN */ +import CustomCSVModal from '../controls/CustomCSVModal'; +/* NGLS - END */ import EmbedCodeContent from '../EmbedCodeContent'; import DashboardsSubMenu from './DashboardsSubMenu'; @@ -393,6 +396,18 @@ export const useExploreAdditionalActionsMenu = ( key={MENU_KEYS.EXPORT_CUSTOM_CSV} icon={} > + {t('Export custom CSV')} + } + modalTitle={t('Export custom CSV')} + modalBody={ + + } + draggable + resizable + responsive + /> {t('Export custom')} {/* NGLS - END */}