From f208dfdce6a4496469186fa083cc8f072442752d Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Mon, 30 Nov 2020 06:45:36 +0100 Subject: [PATCH 01/33] Upgrade react-split --- superset-frontend/package-lock.json | 8 ++++---- superset-frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index b428efe9c4c17..18f81c153bdde 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -43761,12 +43761,12 @@ } }, "react-split": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-split/-/react-split-2.0.4.tgz", - "integrity": "sha512-NBKm9MaqzG/00laMUaS8GS9RnItVSekNNwItgGLMbFTeUa9w4bIY8Co/LszNBnpza9n2am0MXIw3SmyiMnhs+w==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/react-split/-/react-split-2.0.9.tgz", + "integrity": "sha512-IxKtxxmcbNUmWMSd5vlNnlE0jwbgQS1HyQYxt7h8qFgPskSkUTNzMbO838xapmmNf9D+u9B/bdtFnVjt+JC2JA==", "requires": { "prop-types": "^15.5.7", - "split.js": "^1.5.9" + "split.js": "^1.6.0" } }, "react-split-pane": { diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 435118ffd2d73..762aa39189e8a 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -151,7 +151,7 @@ "react-select": "^3.1.0", "react-select-async-paginate": "^0.4.1", "react-sortable-hoc": "^1.11.0", - "react-split": "^2.0.4", + "react-split": "^2.0.9", "react-sticky": "^6.0.3", "react-syntax-highlighter": "^15.3.0", "react-table": "^7.2.1", From 705af79f5cf02fcc63cb9b7504a681f6e1c30299 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Mon, 30 Nov 2020 06:46:08 +0100 Subject: [PATCH 02/33] Implement split on ExploreChartPanel --- .../explore/components/DisplayQueryButton.jsx | 25 -- .../explore/components/ExploreChartPanel.jsx | 258 ++++++++++++++---- 2 files changed, 207 insertions(+), 76 deletions(-) diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index 869674dc30c6e..97413de4dcdde 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -261,22 +261,6 @@ export const DisplayQueryButton = props => { ); }; - const renderResultsModalBody = () => { - if (isLoading) { - return ; - } - if (error) { - return
{error}
; - } - if (data) { - if (data.length === 0) { - return 'No data'; - } - return renderDataTable(); - } - return null; - }; - const renderSamplesModalBody = () => { if (isLoading) { return ; @@ -330,15 +314,6 @@ export const DisplayQueryButton = props => { responsive /> - - {t('View results')}} - modalTitle={t('View results')} - beforeOpen={() => beforeOpen('results')} - modalBody={renderResultsModalBody()} - responsive - /> - {t('View samples')}} diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 674135e43fbfc..ad3c49239efe4 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -16,13 +16,20 @@ * specific language governing permissions and limitations * under the License. */ -import React from 'react'; +import React, { useMemo, useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; +import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; -import { styled } from '@superset-ui/core'; +import { styled, t } from '@superset-ui/core'; +import debounce from 'lodash/debounce'; import { chartPropShape } from '../../dashboard/util/propShapes'; import ChartContainer from '../../chart/ChartContainer'; import ConnectedExploreChartHeader from './ExploreChartHeader'; +import { applyFormattingToTabularData } from '../../utils/common'; +import TableView, { EmptyWrapperType } from '../../components/TableView'; +import { getChartDataRequest } from '../../chart/chartAction'; +import getClientErrorObject from '../../utils/getClientErrorObject'; +import Loading from '../../components/Loading'; const propTypes = { actions: PropTypes.object.isRequired, @@ -49,6 +56,12 @@ const propTypes = { triggerRender: PropTypes.bool, }; +export const EXPLORE_GUTTER_HEIGHT = 5; +export const EXPLORE_GUTTER_MARGIN = 3; +export const CHART_PANEL_PADDING = 30; + +const INITIAL_SIZES = [80, 20]; + const Styles = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; height: 100%; @@ -59,12 +72,134 @@ const Styles = styled.div` & > div:last-of-type { flex-basis: 100%; } + + .gutter { + border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; + border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; + width: 3%; + margin: ${EXPLORE_GUTTER_MARGIN}px 47%; + } + + .gutter.gutter-vertical { + cursor: row-resize; + } `; -class ExploreChartPanel extends React.PureComponent { - renderChart() { - const { chart } = this.props; - const headerHeight = this.props.standalone ? 0 : 80; +const TableContainer = styled.div` + background-color: ${({ theme }) => theme.colors.grayscale.light5}; + z-index: 1; + + .table-condensed { + max-height: 400px; + overflow: auto; + } +`; + +const ExploreChartPanel = props => { + const panelHeadingRef = useRef(null); + const [headerHeight, setHeaderHeight] = useState(props.standalone ? 0 : 50); + + const calcSectionHeight = percent => { + const containerHeight = parseInt(props.height, 10) - headerHeight; + return ( + (containerHeight * percent) / 100 - + (EXPLORE_GUTTER_HEIGHT / 2 + EXPLORE_GUTTER_MARGIN) + ); + }; + + const [chartSectionHeight, setChartSectionHeight] = useState( + calcSectionHeight(INITIAL_SIZES[0]) - CHART_PANEL_PADDING, + ); + const [tableSectionHeight, setTableSectionHeight] = useState( + calcSectionHeight(INITIAL_SIZES[1]), + ); + + const [data, setData] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + const calcHeaderSize = debounce(() => { + setHeaderHeight( + props.standalone ? 0 : panelHeadingRef?.current?.offsetHeight, + ); + }, 100); + calcHeaderSize(); + document.addEventListener('resize', calcHeaderSize); + return () => document.removeEventListener('resize', calcHeaderSize); + }, [props.standalone]); + + useEffect(() => { + setIsLoading(true); + getChartDataRequest({ + formData: props.chart.latestQueryFormData, + resultFormat: 'json', + resultType: 'results', + }) + .then(response => { + // Currently displaying of only first query is supported + const result = response.result[0]; + setData(result.data); + setIsLoading(false); + setError(null); + }) + .catch(response => { + getClientErrorObject(response).then(({ error, statusText }) => { + setError(error || statusText || t('Sorry, An error occurred')); + setIsLoading(false); + }); + }); + }, [props.chart.latestQueryFormData]); + + const tableData = useMemo(() => { + if (!data?.length) { + return []; + } + return applyFormattingToTabularData(data); + }, [data]); + + const columns = useMemo( + () => + data?.length + ? Object.keys(data[0]).map(key => ({ accessor: key, Header: key })) + : [], + [data], + ); + + const onDrag = ([northPercent, southPercent]) => { + setChartSectionHeight( + calcSectionHeight(northPercent) - CHART_PANEL_PADDING, + ); + setTableSectionHeight(calcSectionHeight(southPercent)); + }; + + const renderResultsModalBody = () => { + if (isLoading) { + return ; + } + if (error) { + return
{error}
; + } + if (data) { + if (data.length === 0) { + return No data; + } + return ( + + ); + } + return null; + }; + + const renderChart = () => { + const { chart } = props; return ( @@ -73,67 +208,88 @@ class ExploreChartPanel extends React.PureComponent { height > 0 && ( ) } ); - } + }; - render() { - if (this.props.standalone) { - // dom manipulation hack to get rid of the boostrap theme's body background - const standaloneClass = 'background-transparent'; - const bodyClasses = document.body.className.split(' '); - if (bodyClasses.indexOf(standaloneClass) === -1) { - document.body.className += ` ${standaloneClass}`; - } - return this.renderChart(); + if (props.standalone) { + // dom manipulation hack to get rid of the boostrap theme's body background + const standaloneClass = 'background-transparent'; + const bodyClasses = document.body.className.split(' '); + if (bodyClasses.indexOf(standaloneClass) === -1) { + document.body.className += ` ${standaloneClass}`; } + return renderChart(); + } - const header = ( - - ); + const header = ( + + ); - return ( - -
{header}
-
{this.renderChart()}
-
- ); - } -} + const elementStyle = (dimension, elementSize, gutterSize) => { + return { + [dimension]: `calc(${elementSize}% - ${ + gutterSize + EXPLORE_GUTTER_MARGIN + }px)`, + }; + }; + return ( + +
+ {header} +
+ +
{renderChart()}
+ +
+ {renderResultsModalBody()} +
+
+
+
+ ); +}; ExploreChartPanel.propTypes = propTypes; From cd698ac8d9849e4e8e324c2c2fe7e38052b22da4 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Mon, 30 Nov 2020 17:27:42 +0100 Subject: [PATCH 03/33] Implement tabs with collapse --- .../explore/components/ExploreChartPanel.jsx | 115 +++++++++++++++++- 1 file changed, 109 insertions(+), 6 deletions(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index ad3c49239efe4..e34c947ee0210 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -22,6 +22,7 @@ import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; import { styled, t } from '@superset-ui/core'; import debounce from 'lodash/debounce'; +import Tabs from 'src/common/components/Tabs'; import { chartPropShape } from '../../dashboard/util/propShapes'; import ChartContainer from '../../chart/ChartContainer'; import ConnectedExploreChartHeader from './ExploreChartHeader'; @@ -30,6 +31,7 @@ import TableView, { EmptyWrapperType } from '../../components/TableView'; import { getChartDataRequest } from '../../chart/chartAction'; import getClientErrorObject from '../../utils/getClientErrorObject'; import Loading from '../../components/Loading'; +import Icon from '../../components/Icon'; const propTypes = { actions: PropTypes.object.isRequired, @@ -83,9 +85,21 @@ const Styles = styled.div` .gutter.gutter-vertical { cursor: row-resize; } + + .ant-tabs { + overflow: visible; + .ant-tabs-content-holder { + overflow: visible; + } + .ant-tabs-nav { + padding-left: ${({ theme }) => theme.gridUnit * 5}px; + margin: 0; + background-color: ${({ theme }) => theme.colors.grayscale.light5}; + } + } `; -const TableContainer = styled.div` +const SouthPane = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; z-index: 1; @@ -95,6 +109,40 @@ const TableContainer = styled.div` } `; +const TabsWrapper = styled.div` + height: ${({ contentHeight }) => contentHeight}px; +`; + +const TabTitleContainer = styled.div` + display: flex; + align-items: center; + padding-left: ${({ theme }) => theme.gridUnit}px; +`; + +const CollapseButton = styled.div` + display: flex; + align-items: center; + border-radius: 50%; + margin-left: ${({ theme }) => theme.gridUnit}px; + + :hover { + background-color: ${({ theme, isTabActive }) => + isTabActive ? theme.colors.grayscale.light2 : 'transparent'}; + } + + svg { + transform: ${({ isOpen }) => (isOpen ? 'rotate(0deg)' : 'rotate(180deg)')}; + transition: transform 0.2s ease-out; + } +`; + +const CollapsibleContent = styled.div` + height: 100%; + max-height: ${({ isOpen, height }) => (isOpen ? height : 0)}px; + overflow: ${({ isOpen }) => (isOpen ? 'visible' : 'hidden')}; + transition: max-height 0.2s ease-out; +`; + const ExploreChartPanel = props => { const panelHeadingRef = useRef(null); const [headerHeight, setHeaderHeight] = useState(props.standalone ? 0 : 50); @@ -117,6 +165,8 @@ const ExploreChartPanel = props => { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); + const [openPanelKey, setOpenPanelKey] = useState('1'); + const [activeTabKey, setActiveTabKey] = useState('1'); useEffect(() => { const calcHeaderSize = debounce(() => { @@ -267,6 +317,30 @@ const ExploreChartPanel = props => { }px)`, }; }; + + const TabTitle = ({ name, tabKey }) => { + const isTabActive = tabKey === activeTabKey; + const onClickHandler = () => { + if (isTabActive) { + setOpenPanelKey(openPanelKey === tabKey ? null : tabKey); + } + }; + return ( + + {name}{' '} + + + + + ); + }; return (
@@ -281,11 +355,40 @@ const ExploreChartPanel = props => { elementStyle={elementStyle} >
{renderChart()}
- -
- {renderResultsModalBody()} -
-
+ + + + } + forceRender + key="1" + > + + {renderResultsModalBody()} + + + } + forceRender + key="2" + > + + {renderResultsModalBody()} + + + + + ); From 505b1bd6a99d39c9a64f8eb16e690699a3b2b8aa Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 15:33:28 +0100 Subject: [PATCH 04/33] Fix run query button --- superset-frontend/src/chart/Chart.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/superset-frontend/src/chart/Chart.jsx b/superset-frontend/src/chart/Chart.jsx index 2636751fd6e1e..bb4910c567866 100644 --- a/superset-frontend/src/chart/Chart.jsx +++ b/superset-frontend/src/chart/Chart.jsx @@ -81,6 +81,8 @@ const defaultProps = { }; const Styles = styled.div` + position: relative; + height: 100%; .chart-tooltip { opacity: 0.75; font-size: ${({ theme }) => theme.typography.sizes.s}px; From 40f53b19dfbae0c261e0b735d5cfd7ad86e91f6a Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 17:06:12 +0100 Subject: [PATCH 05/33] Fix copy to clipboard button --- superset-frontend/src/components/CopyToClipboard.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/superset-frontend/src/components/CopyToClipboard.jsx b/superset-frontend/src/components/CopyToClipboard.jsx index 917d0d1e8b4e0..d94a422930081 100644 --- a/superset-frontend/src/components/CopyToClipboard.jsx +++ b/superset-frontend/src/components/CopyToClipboard.jsx @@ -127,6 +127,7 @@ class CopyToClipboard extends React.Component { } renderNotWrapped() { + console.log('DUPAPAAAA'); return ( Date: Wed, 2 Dec 2020 17:06:41 +0100 Subject: [PATCH 06/33] Move table controls to separate file --- .../src/components/CopyToClipboard.jsx | 1 - .../explore/components/DataTableControl.jsx | 91 +++++++++ .../explore/components/DisplayQueryButton.jsx | 90 ++------- .../explore/components/ExploreChartPanel.jsx | 184 +++++++----------- 4 files changed, 178 insertions(+), 188 deletions(-) create mode 100644 superset-frontend/src/explore/components/DataTableControl.jsx diff --git a/superset-frontend/src/components/CopyToClipboard.jsx b/superset-frontend/src/components/CopyToClipboard.jsx index d94a422930081..917d0d1e8b4e0 100644 --- a/superset-frontend/src/components/CopyToClipboard.jsx +++ b/superset-frontend/src/components/CopyToClipboard.jsx @@ -127,7 +127,6 @@ class CopyToClipboard extends React.Component { } renderNotWrapped() { - console.log('DUPAPAAAA'); return ( theme.gridUnit / 2}px + ${({ theme }) => theme.gridUnit * 2.5}px; + font-size: ${({ theme }) => theme.typography.sizes.s}px; + + // needed to override button's first-of-type margin: 0 + && { + margin: 0 ${({ theme }) => theme.gridUnit * 2}px; + } + + i { + padding: 0; + } +`; + +export const CopyToClipboardButton = ({ data }) => ( + + + + } + /> +); + +export const FilterInput = ({ filterText, onChangeHandler }) => ( + +); + +export const RowCount = ({ data }) => ( + +); + +export const useFilteredTableData = (data, filterText) => + useMemo(() => { + if (!data?.length) { + return []; + } + const formattedData = applyFormattingToTabularData(data); + return formattedData.filter(row => + Object.values(row).some(value => + value.toString().toLowerCase().includes(filterText.toLowerCase()), + ), + ); + }, [data, filterText]); + +export const useTableColumns = data => + useMemo( + () => + data?.length + ? Object.keys(data[0]).map(key => ({ accessor: key, Header: key })) + : [], + [data], + ); diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index 97413de4dcdde..73e875bb53edf 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import React, { useState, useMemo } from 'react'; +import React, { useState } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import PropTypes from 'prop-types'; @@ -27,7 +27,7 @@ import sqlSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql'; import jsonSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/json'; import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github'; import { DropdownButton, Row, Col, FormControl } from 'react-bootstrap'; -import { styled, t } from '@superset-ui/core'; +import { t } from '@superset-ui/core'; import { Menu } from 'src/common/components'; import TableView, { EmptyWrapperType } from 'src/components/TableView'; @@ -38,13 +38,15 @@ import { getChartDataRequest } from '../../chart/chartAction'; import downloadAsImage from '../../utils/downloadAsImage'; import Loading from '../../components/Loading'; import ModalTrigger from '../../components/ModalTrigger'; -import RowCountLabel from './RowCountLabel'; -import { - applyFormattingToTabularData, - prepareCopyToClipboardTabularData, -} from '../../utils/common'; import PropertiesModal from './PropertiesModal'; import { sliceUpdated } from '../actions/exploreActions'; +import { + CopyToClipboardButton, + FilterInput, + RowCount, + useFilteredTableData, + useTableColumns, +} from './DataTableControl'; SyntaxHighlighter.registerLanguage('markdown', markdownSyntax); SyntaxHighlighter.registerLanguage('html', htmlSyntax); @@ -66,35 +68,6 @@ const MENU_KEYS = { DOWNLOAD_AS_IMAGE: 'download_as_image', }; -const CopyButton = styled(Button)` - padding: ${({ theme }) => theme.gridUnit / 2}px - ${({ theme }) => theme.gridUnit * 2.5}px; - font-size: ${({ theme }) => theme.typography.sizes.s}px; - - // needed to override button's first-of-type margin: 0 - && { - margin-left: ${({ theme }) => theme.gridUnit * 2}px; - } - - i { - padding: 0; - } -`; - -const CopyButtonViewQuery = styled(Button)` - padding: ${({ theme }) => theme.gridUnit / 2}px - ${({ theme }) => theme.gridUnit * 2.5}px; - font-size: ${({ theme }) => theme.typography.sizes.s}px; - - && { - margin-bottom: 5px; - } - - i { - padding: 0; - } -`; - export const DisplayQueryButton = props => { const { datasource } = props.latestQueryFormData; @@ -110,25 +83,8 @@ export const DisplayQueryButton = props => { const [isPropertiesModalOpen, setIsPropertiesModalOpen] = useState(false); const [menuVisible, setMenuVisible] = useState(false); - const tableData = useMemo(() => { - if (!data?.length) { - return []; - } - const formattedData = applyFormattingToTabularData(data); - return formattedData.filter(row => - Object.values(row).some(value => - value.toString().toLowerCase().includes(filterText.toLowerCase()), - ), - ); - }, [data, filterText]); - - const columns = useMemo( - () => - data?.length - ? Object.keys(data[0]).map(key => ({ accessor: key, Header: key })) - : [], - [data], - ); + const tableData = useFilteredTableData(data, filterText); + const columns = useTableColumns(data); const beforeOpen = resultType => { setIsLoading(true); @@ -225,27 +181,13 @@ export const DisplayQueryButton = props => {
- - - - - } - /> + + - diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index e34c947ee0210..2d0a73b58e5cb 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -16,22 +16,30 @@ * specific language governing permissions and limitations * under the License. */ -import React, { useMemo, useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; import { styled, t } from '@superset-ui/core'; import debounce from 'lodash/debounce'; +import throttle from 'lodash/throttle'; +import { Col, FormControl, Row } from 'react-bootstrap'; +import { Collapse } from 'src/common/components'; import Tabs from 'src/common/components/Tabs'; import { chartPropShape } from '../../dashboard/util/propShapes'; import ChartContainer from '../../chart/ChartContainer'; import ConnectedExploreChartHeader from './ExploreChartHeader'; -import { applyFormattingToTabularData } from '../../utils/common'; import TableView, { EmptyWrapperType } from '../../components/TableView'; import { getChartDataRequest } from '../../chart/chartAction'; import getClientErrorObject from '../../utils/getClientErrorObject'; import Loading from '../../components/Loading'; -import Icon from '../../components/Icon'; +import { + CopyToClipboardButton, + FilterInput, + RowCount, + useFilteredTableData, + useTableColumns, +} from './DataTableControl'; const propTypes = { actions: PropTypes.object.isRequired, @@ -86,69 +94,61 @@ const Styles = styled.div` cursor: row-resize; } - .ant-tabs { - overflow: visible; - .ant-tabs-content-holder { - overflow: visible; + .ant-collapse { + height: 100%; + background-color: ${({ theme }) => theme.colors.grayscale.light5}; + .ant-collapse-item, + .ant-collapse-content, + .ant-collapse-content-box { + height: 100%; } - .ant-tabs-nav { - padding-left: ${({ theme }) => theme.gridUnit * 5}px; - margin: 0; - background-color: ${({ theme }) => theme.colors.grayscale.light5}; + .ant-collapse-header { + padding-top: 0; + padding-bottom: 0; + } + .ant-tabs { + height: 100%; + .ant-tabs-nav { + padding-left: ${({ theme }) => theme.gridUnit * 5}px; + margin: 0; + background-color: ${({ theme }) => theme.colors.grayscale.light5}; + } + .ant-tabs-content-holder { + overflow: hidden; + .ant-tabs-content { + height: 100%; + } + } } } `; +const TableControlsWrapper = styled.div` + display: flex; + align-items: center; +`; + const SouthPane = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; z-index: 1; - - .table-condensed { - max-height: 400px; - overflow: auto; - } `; const TabsWrapper = styled.div` height: ${({ contentHeight }) => contentHeight}px; -`; + overflow: hidden; -const TabTitleContainer = styled.div` - display: flex; - align-items: center; - padding-left: ${({ theme }) => theme.gridUnit}px; -`; - -const CollapseButton = styled.div` - display: flex; - align-items: center; - border-radius: 50%; - margin-left: ${({ theme }) => theme.gridUnit}px; - - :hover { - background-color: ${({ theme, isTabActive }) => - isTabActive ? theme.colors.grayscale.light2 : 'transparent'}; - } - - svg { - transform: ${({ isOpen }) => (isOpen ? 'rotate(0deg)' : 'rotate(180deg)')}; - transition: transform 0.2s ease-out; + .table-condensed { + height: 100%; + overflow: auto; } `; -const CollapsibleContent = styled.div` - height: 100%; - max-height: ${({ isOpen, height }) => (isOpen ? height : 0)}px; - overflow: ${({ isOpen }) => (isOpen ? 'visible' : 'hidden')}; - transition: max-height 0.2s ease-out; -`; - const ExploreChartPanel = props => { const panelHeadingRef = useRef(null); const [headerHeight, setHeaderHeight] = useState(props.standalone ? 0 : 50); const calcSectionHeight = percent => { - const containerHeight = parseInt(props.height, 10) - headerHeight; + const containerHeight = parseInt(props.height, 10) - headerHeight - 30; return ( (containerHeight * percent) / 100 - (EXPLORE_GUTTER_HEIGHT / 2 + EXPLORE_GUTTER_MARGIN) @@ -165,8 +165,7 @@ const ExploreChartPanel = props => { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); - const [openPanelKey, setOpenPanelKey] = useState('1'); - const [activeTabKey, setActiveTabKey] = useState('1'); + const [filterText, setFilterText] = useState(''); useEffect(() => { const calcHeaderSize = debounce(() => { @@ -201,20 +200,12 @@ const ExploreChartPanel = props => { }); }, [props.chart.latestQueryFormData]); - const tableData = useMemo(() => { - if (!data?.length) { - return []; - } - return applyFormattingToTabularData(data); - }, [data]); + const tableData = useFilteredTableData(data, filterText); + const columns = useTableColumns(data); - const columns = useMemo( - () => - data?.length - ? Object.keys(data[0]).map(key => ({ accessor: key, Header: key })) - : [], - [data], - ); + const changeFilterText = event => { + setFilterText(event.target.value); + }; const onDrag = ([northPercent, southPercent]) => { setChartSectionHeight( @@ -318,29 +309,14 @@ const ExploreChartPanel = props => { }; }; - const TabTitle = ({ name, tabKey }) => { - const isTabActive = tabKey === activeTabKey; - const onClickHandler = () => { - if (isTabActive) { - setOpenPanelKey(openPanelKey === tabKey ? null : tabKey); - } - }; - return ( - - {name}{' '} - - - - - ); - }; + const TableControls = ( + + + + + + ); + return (
@@ -357,36 +333,18 @@ const ExploreChartPanel = props => {
{renderChart()}
- - } - forceRender - key="1" - > - - {renderResultsModalBody()} - - - } - forceRender - key="2" - > - - {renderResultsModalBody()} - - - + + + + + {renderResultsModalBody()} + + + {renderResultsModalBody()} + + + + From 85b7c7793a48546cb12a76511395a994ca41d2d9 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 18:16:17 +0100 Subject: [PATCH 07/33] Make component more generic to handle samples --- .../explore/components/ExploreChartPanel.jsx | 135 ++++++++++++------ 1 file changed, 93 insertions(+), 42 deletions(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 2d0a73b58e5cb..e70f9336e9a80 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -22,8 +22,6 @@ import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; import { styled, t } from '@superset-ui/core'; import debounce from 'lodash/debounce'; -import throttle from 'lodash/throttle'; -import { Col, FormControl, Row } from 'react-bootstrap'; import { Collapse } from 'src/common/components'; import Tabs from 'src/common/components/Tabs'; import { chartPropShape } from '../../dashboard/util/propShapes'; @@ -71,6 +69,14 @@ export const EXPLORE_GUTTER_MARGIN = 3; export const CHART_PANEL_PADDING = 30; const INITIAL_SIZES = [80, 20]; +const RESULT_TYPES = { + results: 'results', + samples: 'samples', +}; +const NULLISH_RESULTS_STATE = { + [RESULT_TYPES.results]: null, + [RESULT_TYPES.samples]: null, +}; const Styles = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; @@ -79,6 +85,8 @@ const Styles = styled.div` flex-direction: column; align-items: stretch; align-content: stretch; + overflow: hidden; + & > div:last-of-type { flex-basis: 100%; } @@ -97,7 +105,10 @@ const Styles = styled.div` .ant-collapse { height: 100%; background-color: ${({ theme }) => theme.colors.grayscale.light5}; - .ant-collapse-item, + .ant-collapse-item { + height: 100%; + border: 0; + } .ant-collapse-content, .ant-collapse-content-box { height: 100%; @@ -126,6 +137,10 @@ const Styles = styled.div` const TableControlsWrapper = styled.div` display: flex; align-items: center; + + span { + flex-shrink: 0; + } `; const SouthPane = styled.div` @@ -162,10 +177,11 @@ const ExploreChartPanel = props => { calcSectionHeight(INITIAL_SIZES[1]), ); - const [data, setData] = useState(null); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); + const [data, setData] = useState(NULLISH_RESULTS_STATE); + const [isLoading, setIsLoading] = useState(NULLISH_RESULTS_STATE); + const [error, setError] = useState(NULLISH_RESULTS_STATE); const [filterText, setFilterText] = useState(''); + const [activeTabKey, setActiveTabKey] = useState(RESULT_TYPES.results); useEffect(() => { const calcHeaderSize = debounce(() => { @@ -179,29 +195,59 @@ const ExploreChartPanel = props => { }, [props.standalone]); useEffect(() => { - setIsLoading(true); - getChartDataRequest({ - formData: props.chart.latestQueryFormData, - resultFormat: 'json', - resultType: 'results', - }) - .then(response => { - // Currently displaying of only first query is supported - const result = response.result[0]; - setData(result.data); - setIsLoading(false); - setError(null); + const getData = resultType => { + setIsLoading(prevIsLoading => ({ ...prevIsLoading, [resultType]: true })); + return getChartDataRequest({ + formData: props.chart.latestQueryFormData, + resultFormat: 'json', + resultType, }) - .catch(response => { - getClientErrorObject(response).then(({ error, statusText }) => { - setError(error || statusText || t('Sorry, An error occurred')); - setIsLoading(false); + .then(response => { + // Currently displaying of only first query is supported + const result = response.result[0]; + setData(prevData => ({ ...prevData, [resultType]: result.data })); + setIsLoading(prevIsLoading => ({ + ...prevIsLoading, + [resultType]: false, + })); + setError(prevError => ({ + ...prevError, + [resultType]: NULLISH_RESULTS_STATE, + })); + }) + .catch(response => { + getClientErrorObject(response).then(({ error, statusText }) => { + setError(prevError => ({ + ...prevError, + [resultType]: + error || statusText || t('Sorry, An error occurred'), + })); + setIsLoading(prevIsLoading => ({ + ...prevIsLoading, + [resultType]: false, + })); + }); }); - }); + }; + getData(RESULT_TYPES.results); + getData(RESULT_TYPES.samples); }, [props.chart.latestQueryFormData]); - const tableData = useFilteredTableData(data, filterText); - const columns = useTableColumns(data); + const filteredData = { + [RESULT_TYPES.results]: useFilteredTableData( + data[RESULT_TYPES.results], + filterText, + ), + [RESULT_TYPES.samples]: useFilteredTableData( + data[RESULT_TYPES.samples], + filterText, + ), + }; + + const columns = { + [RESULT_TYPES.results]: useTableColumns(data[RESULT_TYPES.results]), + [RESULT_TYPES.samples]: useTableColumns(data[RESULT_TYPES.samples]), + }; const changeFilterText = event => { setFilterText(event.target.value); @@ -214,21 +260,21 @@ const ExploreChartPanel = props => { setTableSectionHeight(calcSectionHeight(southPercent)); }; - const renderResultsModalBody = () => { - if (isLoading) { + const renderDataTable = type => { + if (isLoading[type]) { return ; } - if (error) { - return
{error}
; + if (error[type]) { + return
{error[type]}
; } - if (data) { - if (data.length === 0) { + if (data[type]) { + if (data[type].length === 0) { return No data; } return ( { const TableControls = ( - - + + ); @@ -324,7 +370,7 @@ const ExploreChartPanel = props => {
{ - - - - {renderResultsModalBody()} + + + + {renderDataTable(RESULT_TYPES.results)} - - {renderResultsModalBody()} + + {renderDataTable(RESULT_TYPES.samples)} From 677830b6da546d8fa7d49327feeb515664dbb19e Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 18:18:02 +0100 Subject: [PATCH 08/33] Remove samples from DisplayQueryButton --- .../explore/components/DisplayQueryButton.jsx | 69 +------------------ 1 file changed, 1 insertion(+), 68 deletions(-) diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index 73e875bb53edf..b1617b104ce7c 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -26,11 +26,10 @@ import markdownSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/mar import sqlSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql'; import jsonSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/json'; import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github'; -import { DropdownButton, Row, Col, FormControl } from 'react-bootstrap'; +import { DropdownButton } from 'react-bootstrap'; import { t } from '@superset-ui/core'; import { Menu } from 'src/common/components'; -import TableView, { EmptyWrapperType } from 'src/components/TableView'; import Button from 'src/components/Button'; import getClientErrorObject from '../../utils/getClientErrorObject'; import CopyToClipboard from '../../components/CopyToClipboard'; @@ -40,13 +39,6 @@ import Loading from '../../components/Loading'; import ModalTrigger from '../../components/ModalTrigger'; import PropertiesModal from './PropertiesModal'; import { sliceUpdated } from '../actions/exploreActions'; -import { - CopyToClipboardButton, - FilterInput, - RowCount, - useFilteredTableData, - useTableColumns, -} from './DataTableControl'; SyntaxHighlighter.registerLanguage('markdown', markdownSyntax); SyntaxHighlighter.registerLanguage('html', htmlSyntax); @@ -73,19 +65,14 @@ export const DisplayQueryButton = props => { const [language, setLanguage] = useState(null); const [query, setQuery] = useState(null); - const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); - const [filterText, setFilterText] = useState(''); const [sqlSupported] = useState( datasource && datasource.split('__')[1] === 'table', ); const [isPropertiesModalOpen, setIsPropertiesModalOpen] = useState(false); const [menuVisible, setMenuVisible] = useState(false); - const tableData = useFilteredTableData(data, filterText); - const columns = useTableColumns(data); - const beforeOpen = resultType => { setIsLoading(true); @@ -99,7 +86,6 @@ export const DisplayQueryButton = props => { const result = response.result[0]; setLanguage(result.language); setQuery(result.query); - setData(result.data); setIsLoading(false); setError(null); }) @@ -111,10 +97,6 @@ export const DisplayQueryButton = props => { }); }; - const changeFilterText = event => { - setFilterText(event.target.value); - }; - const openPropertiesModal = () => { setIsPropertiesModalOpen(true); }; @@ -176,46 +158,6 @@ export const DisplayQueryButton = props => { return null; }; - const renderDataTable = () => { - return ( -
- - - - - - - - - - -
- ); - }; - - const renderSamplesModalBody = () => { - if (isLoading) { - return ; - } - if (error) { - return
{error}
; - } - if (data) { - return renderDataTable(); - } - return null; - }; - const { slice } = props; return ( { responsive /> - - {t('View samples')}} - modalTitle={t('View samples')} - beforeOpen={() => beforeOpen('samples')} - modalBody={renderSamplesModalBody()} - responsive - /> - {sqlSupported && ( {t('Run in SQL Lab')} From a3cc158ee4a876096b87bc2c430ef5eb09ac9934 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 18:28:53 +0100 Subject: [PATCH 09/33] Move data tables to separate file --- .../src/explore/components/DataTablesPane.jsx | 190 ++++++++++++++++++ .../explore/components/ExploreChartPanel.jsx | 171 +--------------- 2 files changed, 196 insertions(+), 165 deletions(-) create mode 100644 superset-frontend/src/explore/components/DataTablesPane.jsx diff --git a/superset-frontend/src/explore/components/DataTablesPane.jsx b/superset-frontend/src/explore/components/DataTablesPane.jsx new file mode 100644 index 0000000000000..479a29e7281eb --- /dev/null +++ b/superset-frontend/src/explore/components/DataTablesPane.jsx @@ -0,0 +1,190 @@ +/** + * 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, t } from '@superset-ui/core'; +import { + CopyToClipboardButton, + FilterInput, + RowCount, + useFilteredTableData, + useTableColumns, +} from './DataTableControl'; +import { Collapse } from '../../common/components'; +import Tabs from '../../common/components/Tabs'; +import Loading from '../../components/Loading'; +import TableView, { EmptyWrapperType } from '../../components/TableView'; +import { getChartDataRequest } from '../../chart/chartAction'; +import getClientErrorObject from '../../utils/getClientErrorObject'; + +const RESULT_TYPES = { + results: 'results', + samples: 'samples', +}; +const NULLISH_RESULTS_STATE = { + [RESULT_TYPES.results]: null, + [RESULT_TYPES.samples]: null, +}; + +const TableControlsWrapper = styled.div` + display: flex; + align-items: center; + + span { + flex-shrink: 0; + } +`; + +const SouthPane = styled.div` + background-color: ${({ theme }) => theme.colors.grayscale.light5}; + z-index: 1; +`; + +const TabsWrapper = styled.div` + height: ${({ contentHeight }) => contentHeight}px; + overflow: hidden; + + .table-condensed { + height: 100%; + overflow: auto; + } +`; + +export const DataTablesPane = ({ queryFormData, tableSectionHeight }) => { + const [data, setData] = useState(NULLISH_RESULTS_STATE); + const [isLoading, setIsLoading] = useState(NULLISH_RESULTS_STATE); + const [error, setError] = useState(NULLISH_RESULTS_STATE); + const [filterText, setFilterText] = useState(''); + const [activeTabKey, setActiveTabKey] = useState(RESULT_TYPES.results); + + useEffect(() => { + const getData = resultType => { + setIsLoading(prevIsLoading => ({ ...prevIsLoading, [resultType]: true })); + return getChartDataRequest({ + formData: queryFormData, + resultFormat: 'json', + resultType, + }) + .then(response => { + // Currently displaying of only first query is supported + const result = response.result[0]; + setData(prevData => ({ ...prevData, [resultType]: result.data })); + setIsLoading(prevIsLoading => ({ + ...prevIsLoading, + [resultType]: false, + })); + setError(prevError => ({ + ...prevError, + [resultType]: null, + })); + }) + .catch(response => { + getClientErrorObject(response).then(({ error, statusText }) => { + setError(prevError => ({ + ...prevError, + [resultType]: + error || statusText || t('Sorry, An error occurred'), + })); + setIsLoading(prevIsLoading => ({ + ...prevIsLoading, + [resultType]: false, + })); + }); + }); + }; + getData(RESULT_TYPES.results); + getData(RESULT_TYPES.samples); + }, [queryFormData]); + + const filteredData = { + [RESULT_TYPES.results]: useFilteredTableData( + data[RESULT_TYPES.results], + filterText, + ), + [RESULT_TYPES.samples]: useFilteredTableData( + data[RESULT_TYPES.samples], + filterText, + ), + }; + + const columns = { + [RESULT_TYPES.results]: useTableColumns(data[RESULT_TYPES.results]), + [RESULT_TYPES.samples]: useTableColumns(data[RESULT_TYPES.samples]), + }; + + const changeFilterText = event => { + setFilterText(event.target.value); + }; + + const renderDataTable = type => { + if (isLoading[type]) { + return ; + } + if (error[type]) { + return
{error[type]}
; + } + if (data[type]) { + if (data[type].length === 0) { + return No data; + } + return ( + + ); + } + return null; + }; + + const TableControls = ( + + + + + + ); + + return ( + + + + + + + {renderDataTable(RESULT_TYPES.results)} + + + {renderDataTable(RESULT_TYPES.samples)} + + + + + + + ); +}; diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index e70f9336e9a80..150cdb62e8031 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -20,24 +20,12 @@ import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; -import { styled, t } from '@superset-ui/core'; +import { styled } from '@superset-ui/core'; import debounce from 'lodash/debounce'; -import { Collapse } from 'src/common/components'; -import Tabs from 'src/common/components/Tabs'; import { chartPropShape } from '../../dashboard/util/propShapes'; import ChartContainer from '../../chart/ChartContainer'; import ConnectedExploreChartHeader from './ExploreChartHeader'; -import TableView, { EmptyWrapperType } from '../../components/TableView'; -import { getChartDataRequest } from '../../chart/chartAction'; -import getClientErrorObject from '../../utils/getClientErrorObject'; -import Loading from '../../components/Loading'; -import { - CopyToClipboardButton, - FilterInput, - RowCount, - useFilteredTableData, - useTableColumns, -} from './DataTableControl'; +import { DataTablesPane } from './DataTablesPane'; const propTypes = { actions: PropTypes.object.isRequired, @@ -69,14 +57,6 @@ export const EXPLORE_GUTTER_MARGIN = 3; export const CHART_PANEL_PADDING = 30; const INITIAL_SIZES = [80, 20]; -const RESULT_TYPES = { - results: 'results', - samples: 'samples', -}; -const NULLISH_RESULTS_STATE = { - [RESULT_TYPES.results]: null, - [RESULT_TYPES.samples]: null, -}; const Styles = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; @@ -134,30 +114,6 @@ const Styles = styled.div` } `; -const TableControlsWrapper = styled.div` - display: flex; - align-items: center; - - span { - flex-shrink: 0; - } -`; - -const SouthPane = styled.div` - background-color: ${({ theme }) => theme.colors.grayscale.light5}; - z-index: 1; -`; - -const TabsWrapper = styled.div` - height: ${({ contentHeight }) => contentHeight}px; - overflow: hidden; - - .table-condensed { - height: 100%; - overflow: auto; - } -`; - const ExploreChartPanel = props => { const panelHeadingRef = useRef(null); const [headerHeight, setHeaderHeight] = useState(props.standalone ? 0 : 50); @@ -177,12 +133,6 @@ const ExploreChartPanel = props => { calcSectionHeight(INITIAL_SIZES[1]), ); - const [data, setData] = useState(NULLISH_RESULTS_STATE); - const [isLoading, setIsLoading] = useState(NULLISH_RESULTS_STATE); - const [error, setError] = useState(NULLISH_RESULTS_STATE); - const [filterText, setFilterText] = useState(''); - const [activeTabKey, setActiveTabKey] = useState(RESULT_TYPES.results); - useEffect(() => { const calcHeaderSize = debounce(() => { setHeaderHeight( @@ -194,65 +144,6 @@ const ExploreChartPanel = props => { return () => document.removeEventListener('resize', calcHeaderSize); }, [props.standalone]); - useEffect(() => { - const getData = resultType => { - setIsLoading(prevIsLoading => ({ ...prevIsLoading, [resultType]: true })); - return getChartDataRequest({ - formData: props.chart.latestQueryFormData, - resultFormat: 'json', - resultType, - }) - .then(response => { - // Currently displaying of only first query is supported - const result = response.result[0]; - setData(prevData => ({ ...prevData, [resultType]: result.data })); - setIsLoading(prevIsLoading => ({ - ...prevIsLoading, - [resultType]: false, - })); - setError(prevError => ({ - ...prevError, - [resultType]: NULLISH_RESULTS_STATE, - })); - }) - .catch(response => { - getClientErrorObject(response).then(({ error, statusText }) => { - setError(prevError => ({ - ...prevError, - [resultType]: - error || statusText || t('Sorry, An error occurred'), - })); - setIsLoading(prevIsLoading => ({ - ...prevIsLoading, - [resultType]: false, - })); - }); - }); - }; - getData(RESULT_TYPES.results); - getData(RESULT_TYPES.samples); - }, [props.chart.latestQueryFormData]); - - const filteredData = { - [RESULT_TYPES.results]: useFilteredTableData( - data[RESULT_TYPES.results], - filterText, - ), - [RESULT_TYPES.samples]: useFilteredTableData( - data[RESULT_TYPES.samples], - filterText, - ), - }; - - const columns = { - [RESULT_TYPES.results]: useTableColumns(data[RESULT_TYPES.results]), - [RESULT_TYPES.samples]: useTableColumns(data[RESULT_TYPES.samples]), - }; - - const changeFilterText = event => { - setFilterText(event.target.value); - }; - const onDrag = ([northPercent, southPercent]) => { setChartSectionHeight( calcSectionHeight(northPercent) - CHART_PANEL_PADDING, @@ -260,31 +151,6 @@ const ExploreChartPanel = props => { setTableSectionHeight(calcSectionHeight(southPercent)); }; - const renderDataTable = type => { - if (isLoading[type]) { - return ; - } - if (error[type]) { - return
{error[type]}
; - } - if (data[type]) { - if (data[type].length === 0) { - return No data; - } - return ( - - ); - } - return null; - }; - const renderChart = () => { const { chart } = props; @@ -355,14 +221,6 @@ const ExploreChartPanel = props => { }; }; - const TableControls = ( - - - - - - ); - return (
@@ -377,27 +235,10 @@ const ExploreChartPanel = props => { elementStyle={elementStyle} >
{renderChart()}
- - - - - - - {renderDataTable(RESULT_TYPES.results)} - - - {renderDataTable(RESULT_TYPES.samples)} - - - - - - + ); From e63cc63be4a1e7b319659211cf93dac1d52cf4f7 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 19:00:35 +0100 Subject: [PATCH 10/33] Make split dynamically controlled --- .../src/explore/components/DataTablesPane.jsx | 15 ++++++++-- .../explore/components/ExploreChartPanel.jsx | 28 +++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.jsx b/superset-frontend/src/explore/components/DataTablesPane.jsx index 479a29e7281eb..08fdbc8774801 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.jsx +++ b/superset-frontend/src/explore/components/DataTablesPane.jsx @@ -17,6 +17,7 @@ * under the License. */ import React, { useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; import { styled, t } from '@superset-ui/core'; import { CopyToClipboardButton, @@ -65,7 +66,11 @@ const TabsWrapper = styled.div` } `; -export const DataTablesPane = ({ queryFormData, tableSectionHeight }) => { +export const DataTablesPane = ({ + queryFormData, + tableSectionHeight, + onCollapseChange, +}) => { const [data, setData] = useState(NULLISH_RESULTS_STATE); const [isLoading, setIsLoading] = useState(NULLISH_RESULTS_STATE); const [error, setError] = useState(NULLISH_RESULTS_STATE); @@ -167,7 +172,7 @@ export const DataTablesPane = ({ queryFormData, tableSectionHeight }) => { return ( - + { ); }; + +DataTablesPane.propTypes = { + tableSectionHeight: PropTypes.number, + queryFormData: PropTypes.object, + onCollapseChange: PropTypes.func, +}; diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 150cdb62e8031..b2f184d6a669b 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -56,7 +56,8 @@ export const EXPLORE_GUTTER_HEIGHT = 5; export const EXPLORE_GUTTER_MARGIN = 3; export const CHART_PANEL_PADDING = 30; -const INITIAL_SIZES = [80, 20]; +const INITIAL_SIZES = [90, 10]; +const MIN_SIZES = [300, 50]; const Styles = styled.div` background-color: ${({ theme }) => theme.colors.grayscale.light5}; @@ -117,6 +118,7 @@ const Styles = styled.div` const ExploreChartPanel = props => { const panelHeadingRef = useRef(null); const [headerHeight, setHeaderHeight] = useState(props.standalone ? 0 : 50); + const [splitSizes, setSplitSizes] = useState(INITIAL_SIZES); const calcSectionHeight = percent => { const containerHeight = parseInt(props.height, 10) - headerHeight - 30; @@ -144,13 +146,28 @@ const ExploreChartPanel = props => { return () => document.removeEventListener('resize', calcHeaderSize); }, [props.standalone]); - const onDrag = ([northPercent, southPercent]) => { + const recalcPanelSizes = ([northPercent, southPercent]) => { setChartSectionHeight( calcSectionHeight(northPercent) - CHART_PANEL_PADDING, ); setTableSectionHeight(calcSectionHeight(southPercent)); }; + const onCollapseChange = openPanelName => { + const defaultSouthPaneOpenHeightPercent = 40; + let splitSizes; + if (!openPanelName) { + splitSizes = INITIAL_SIZES; + } else { + splitSizes = [ + 100 - defaultSouthPaneOpenHeightPercent, + defaultSouthPaneOpenHeightPercent, + ]; + } + setSplitSizes(splitSizes); + recalcPanelSizes(splitSizes); + }; + const renderChart = () => { const { chart } = props; @@ -227,17 +244,18 @@ const ExploreChartPanel = props => { {header}
{renderChart()}
From 0826a58cdf26c350f1d77086a7bf69ff3555de8f Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Wed, 2 Dec 2020 19:05:03 +0100 Subject: [PATCH 11/33] Fix unit test --- .../explore/components/DisplayQueryButton_spec.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx b/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx index 4d1bb4556cfad..263656a6a9ced 100644 --- a/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx +++ b/superset-frontend/spec/javascripts/explore/components/DisplayQueryButton_spec.jsx @@ -50,7 +50,7 @@ describe('DisplayQueryButton', () => { theme: supersetTheme, }, }); - expect(wrapper.find(ModalTrigger)).toHaveLength(3); - expect(wrapper.find(Menu.Item)).toHaveLength(5); + expect(wrapper.find(ModalTrigger)).toHaveLength(1); + expect(wrapper.find(Menu.Item)).toHaveLength(3); }); }); From c51ef6ab10da7ad00f7190de7391f8ebed9d3cdc Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 10:14:04 +0100 Subject: [PATCH 12/33] Fix arrow not centered --- .../src/explore/components/ExploreChartPanel.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index b2f184d6a669b..f11d28f1721ea 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -60,7 +60,6 @@ const INITIAL_SIZES = [90, 10]; const MIN_SIZES = [300, 50]; const Styles = styled.div` - background-color: ${({ theme }) => theme.colors.grayscale.light5}; height: 100%; display: flex; flex-direction: column; @@ -95,15 +94,19 @@ const Styles = styled.div` height: 100%; } .ant-collapse-header { + background-color: ${({ theme }) => theme.colors.grayscale.light5}; padding-top: 0; padding-bottom: 0; + font-weight: ${({ theme }) => theme.typography.weights.bold}; + span { + top: 5px; // not a theme variable, override necessary after setting paddings to 0 to center arrow + } } .ant-tabs { height: 100%; .ant-tabs-nav { padding-left: ${({ theme }) => theme.gridUnit * 5}px; margin: 0; - background-color: ${({ theme }) => theme.colors.grayscale.light5}; } .ant-tabs-content-holder { overflow: hidden; From 976197e2447e7d73150bf0ee7bae1d7e59da14aa Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 10:18:48 +0100 Subject: [PATCH 13/33] fixup! Fix arrow not centered --- superset-frontend/src/explore/components/ExploreChartPanel.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index f11d28f1721ea..c987cc3d1d84a 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -98,7 +98,7 @@ const Styles = styled.div` padding-top: 0; padding-bottom: 0; font-weight: ${({ theme }) => theme.typography.weights.bold}; - span { + & > .ant-collapse-arrow { top: 5px; // not a theme variable, override necessary after setting paddings to 0 to center arrow } } From f9fdaa6a497dcf7840b7fad3975940cfafd217cb Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 10:36:13 +0100 Subject: [PATCH 14/33] Change copy button paddings --- .../src/explore/components/DataTableControl.jsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTableControl.jsx b/superset-frontend/src/explore/components/DataTableControl.jsx index 776297c14ede4..3cb73f63b49d8 100644 --- a/superset-frontend/src/explore/components/DataTableControl.jsx +++ b/superset-frontend/src/explore/components/DataTableControl.jsx @@ -28,8 +28,6 @@ import { import CopyToClipboard from '../../components/CopyToClipboard'; const CopyButton = styled(Button)` - padding: ${({ theme }) => theme.gridUnit / 2}px - ${({ theme }) => theme.gridUnit * 2.5}px; font-size: ${({ theme }) => theme.typography.sizes.s}px; // needed to override button's first-of-type margin: 0 @@ -47,7 +45,7 @@ export const CopyToClipboardButton = ({ data }) => ( text={data ? prepareCopyToClipboardTabularData(data) : ''} wrapped={false} copyNode={ - + } @@ -60,12 +58,11 @@ export const FilterInput = ({ filterText, onChangeHandler }) => ( bsSize="sm" value={filterText} onChange={onChangeHandler} - style={{ paddingBottom: '5px' }} /> ); export const RowCount = ({ data }) => ( - + ); export const useFilteredTableData = (data, filterText) => From f733f4f8a8f980a246a831d11038a6d0b4177275 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 10:36:26 +0100 Subject: [PATCH 15/33] Use translations --- superset-frontend/src/explore/components/DataTablesPane.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.jsx b/superset-frontend/src/explore/components/DataTablesPane.jsx index 08fdbc8774801..ed5634b437ec0 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.jsx +++ b/superset-frontend/src/explore/components/DataTablesPane.jsx @@ -173,17 +173,17 @@ export const DataTablesPane = ({ - + - + {renderDataTable(RESULT_TYPES.results)} - + {renderDataTable(RESULT_TYPES.samples)} From 62931daf56a8c6cf17b443612800b614859228ab Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 10:38:56 +0100 Subject: [PATCH 16/33] Fix grammar in a comment --- superset-frontend/src/explore/components/DataTablesPane.jsx | 2 +- superset-frontend/src/explore/components/DisplayQueryButton.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.jsx b/superset-frontend/src/explore/components/DataTablesPane.jsx index ed5634b437ec0..6b8a01b921587 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.jsx +++ b/superset-frontend/src/explore/components/DataTablesPane.jsx @@ -86,7 +86,7 @@ export const DataTablesPane = ({ resultType, }) .then(response => { - // Currently displaying of only first query is supported + // Only displaying the first query is currently supported const result = response.result[0]; setData(prevData => ({ ...prevData, [resultType]: result.data })); setIsLoading(prevIsLoading => ({ diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index b1617b104ce7c..f1fe2d94bca9c 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -82,7 +82,7 @@ export const DisplayQueryButton = props => { resultType, }) .then(response => { - // Currently displaying of only first query is supported + // Only displaying the first query is currently supported const result = response.result[0]; setLanguage(result.language); setQuery(result.query); From 1c1dd2c834bb77bb4e0c79694772215a99a48d04 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 10:41:46 +0100 Subject: [PATCH 17/33] Fix imports --- .../src/explore/components/DataTableControl.jsx | 6 +++--- .../src/explore/components/DataTablesPane.jsx | 12 ++++++------ .../src/explore/components/ExploreChartPanel.jsx | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTableControl.jsx b/superset-frontend/src/explore/components/DataTableControl.jsx index 3cb73f63b49d8..f39e61c6eb99f 100644 --- a/superset-frontend/src/explore/components/DataTableControl.jsx +++ b/superset-frontend/src/explore/components/DataTableControl.jsx @@ -19,13 +19,13 @@ import React, { useMemo } from 'react'; import { styled, t } from '@superset-ui/core'; import { FormControl } from 'react-bootstrap'; -import Button from '../../components/Button'; +import Button from 'src/components/Button'; import RowCountLabel from './RowCountLabel'; import { applyFormattingToTabularData, prepareCopyToClipboardTabularData, -} from '../../utils/common'; -import CopyToClipboard from '../../components/CopyToClipboard'; +} from 'src/utils/common'; +import CopyToClipboard from 'src/components/CopyToClipboard'; const CopyButton = styled(Button)` font-size: ${({ theme }) => theme.typography.sizes.s}px; diff --git a/superset-frontend/src/explore/components/DataTablesPane.jsx b/superset-frontend/src/explore/components/DataTablesPane.jsx index 6b8a01b921587..acc01b32598ab 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.jsx +++ b/superset-frontend/src/explore/components/DataTablesPane.jsx @@ -26,12 +26,12 @@ import { useFilteredTableData, useTableColumns, } from './DataTableControl'; -import { Collapse } from '../../common/components'; -import Tabs from '../../common/components/Tabs'; -import Loading from '../../components/Loading'; -import TableView, { EmptyWrapperType } from '../../components/TableView'; -import { getChartDataRequest } from '../../chart/chartAction'; -import getClientErrorObject from '../../utils/getClientErrorObject'; +import { Collapse } from 'src/common/components'; +import Tabs from 'src/common/components/Tabs'; +import Loading from 'src/components/Loading'; +import TableView, { EmptyWrapperType } from 'src/components/TableView'; +import { getChartDataRequest } from 'src/chart/chartAction'; +import getClientErrorObject from 'src/utils/getClientErrorObject'; const RESULT_TYPES = { results: 'results', diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index c987cc3d1d84a..5842e4a51044b 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -22,8 +22,8 @@ import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; import { styled } from '@superset-ui/core'; import debounce from 'lodash/debounce'; -import { chartPropShape } from '../../dashboard/util/propShapes'; -import ChartContainer from '../../chart/ChartContainer'; +import { chartPropShape } from 'src/dashboard/util/propShapes'; +import ChartContainer from 'src/chart/ChartContainer'; import ConnectedExploreChartHeader from './ExploreChartHeader'; import { DataTablesPane } from './DataTablesPane'; From 879f97352ce9c72fd138d5beb8aaf15d14945a66 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 11:58:04 +0100 Subject: [PATCH 18/33] Use grid units --- .../src/explore/components/ExploreChartPanel.jsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 5842e4a51044b..884a59d0464df 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -52,12 +52,13 @@ const propTypes = { triggerRender: PropTypes.bool, }; -export const EXPLORE_GUTTER_HEIGHT = 5; -export const EXPLORE_GUTTER_MARGIN = 3; -export const CHART_PANEL_PADDING = 30; +const EXPLORE_GUTTER_HEIGHT = 5; +const EXPLORE_GUTTER_MARGIN = 3; +const CHART_PANEL_PADDING = 30; const INITIAL_SIZES = [90, 10]; const MIN_SIZES = [300, 50]; +const DEFAULT_SOUTH_PANE_HEIGHT_PERCENT = 40; const Styles = styled.div` height: 100%; @@ -74,8 +75,8 @@ const Styles = styled.div` .gutter { border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; - width: 3%; - margin: ${EXPLORE_GUTTER_MARGIN}px 47%; + width: ${({ theme }) => theme.gridUnit * 9}px; + margin: ${EXPLORE_GUTTER_MARGIN}px auto; } .gutter.gutter-vertical { @@ -157,14 +158,13 @@ const ExploreChartPanel = props => { }; const onCollapseChange = openPanelName => { - const defaultSouthPaneOpenHeightPercent = 40; let splitSizes; if (!openPanelName) { splitSizes = INITIAL_SIZES; } else { splitSizes = [ - 100 - defaultSouthPaneOpenHeightPercent, - defaultSouthPaneOpenHeightPercent, + 100 - DEFAULT_SOUTH_PANE_HEIGHT_PERCENT, + DEFAULT_SOUTH_PANE_HEIGHT_PERCENT, ]; } setSplitSizes(splitSizes); From 694099d42930eabef77b1875c1b222b7ad97604f Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 12:46:37 +0100 Subject: [PATCH 19/33] Convert new files to typescript --- ...aTableControl.jsx => DataTableControl.tsx} | 22 +++++--- ...{DataTablesPane.jsx => DataTablesPane.tsx} | 55 +++++++++++-------- .../explore/components/ExploreChartPanel.jsx | 2 +- 3 files changed, 47 insertions(+), 32 deletions(-) rename superset-frontend/src/explore/components/{DataTableControl.jsx => DataTableControl.tsx} (81%) rename superset-frontend/src/explore/components/{DataTablesPane.jsx => DataTablesPane.tsx} (84%) diff --git a/superset-frontend/src/explore/components/DataTableControl.jsx b/superset-frontend/src/explore/components/DataTableControl.tsx similarity index 81% rename from superset-frontend/src/explore/components/DataTableControl.jsx rename to superset-frontend/src/explore/components/DataTableControl.tsx index f39e61c6eb99f..c47b613b222e3 100644 --- a/superset-frontend/src/explore/components/DataTableControl.jsx +++ b/superset-frontend/src/explore/components/DataTableControl.tsx @@ -20,12 +20,12 @@ import React, { useMemo } from 'react'; import { styled, t } from '@superset-ui/core'; import { FormControl } from 'react-bootstrap'; import Button from 'src/components/Button'; -import RowCountLabel from './RowCountLabel'; import { applyFormattingToTabularData, prepareCopyToClipboardTabularData, } from 'src/utils/common'; import CopyToClipboard from 'src/components/CopyToClipboard'; +import RowCountLabel from './RowCountLabel'; const CopyButton = styled(Button)` font-size: ${({ theme }) => theme.typography.sizes.s}px; @@ -40,7 +40,7 @@ const CopyButton = styled(Button)` } `; -export const CopyToClipboardButton = ({ data }) => ( +export const CopyToClipboardButton = ({ data }: { data: object }) => ( ( /> ); -export const FilterInput = ({ filterText, onChangeHandler }) => ( +export const FilterInput = ({ + filterText, + onChangeHandler, +}: { + filterText: string; + onChangeHandler(event: React.ChangeEvent): void; +}) => ( onChangeHandler(event as any)} /> ); -export const RowCount = ({ data }) => ( +export const RowCount = ({ data }: { data: object[] }) => ( ); -export const useFilteredTableData = (data, filterText) => +export const useFilteredTableData = (filterText: string, data?: object[]) => useMemo(() => { if (!data?.length) { return []; } const formattedData = applyFormattingToTabularData(data); - return formattedData.filter(row => + return formattedData.filter((row: object) => Object.values(row).some(value => value.toString().toLowerCase().includes(filterText.toLowerCase()), ), ); }, [data, filterText]); -export const useTableColumns = data => +export const useTableColumns = (data?: object[]) => useMemo( () => data?.length diff --git a/superset-frontend/src/explore/components/DataTablesPane.jsx b/superset-frontend/src/explore/components/DataTablesPane.tsx similarity index 84% rename from superset-frontend/src/explore/components/DataTablesPane.jsx rename to superset-frontend/src/explore/components/DataTablesPane.tsx index acc01b32598ab..e3cf3da694fb8 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.jsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -19,6 +19,12 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { styled, t } from '@superset-ui/core'; +import { Collapse } from 'src/common/components'; +import Tabs from 'src/common/components/Tabs'; +import Loading from 'src/components/Loading'; +import TableView, { EmptyWrapperType } from 'src/components/TableView'; +import { getChartDataRequest } from 'src/chart/chartAction'; +import getClientErrorObject from 'src/utils/getClientErrorObject'; import { CopyToClipboardButton, FilterInput, @@ -26,20 +32,15 @@ import { useFilteredTableData, useTableColumns, } from './DataTableControl'; -import { Collapse } from 'src/common/components'; -import Tabs from 'src/common/components/Tabs'; -import Loading from 'src/components/Loading'; -import TableView, { EmptyWrapperType } from 'src/components/TableView'; -import { getChartDataRequest } from 'src/chart/chartAction'; -import getClientErrorObject from 'src/utils/getClientErrorObject'; const RESULT_TYPES = { - results: 'results', - samples: 'samples', + results: 'results' as const, + samples: 'samples' as const, }; + const NULLISH_RESULTS_STATE = { - [RESULT_TYPES.results]: null, - [RESULT_TYPES.samples]: null, + [RESULT_TYPES.results]: undefined, + [RESULT_TYPES.samples]: undefined, }; const TableControlsWrapper = styled.div` @@ -56,7 +57,7 @@ const SouthPane = styled.div` z-index: 1; `; -const TabsWrapper = styled.div` +const TabsWrapper = styled.div<{ contentHeight: number }>` height: ${({ contentHeight }) => contentHeight}px; overflow: hidden; @@ -70,15 +71,24 @@ export const DataTablesPane = ({ queryFormData, tableSectionHeight, onCollapseChange, +}: { + queryFormData: object; + tableSectionHeight: number; + onCollapseChange: (openPanelName: string) => void; }) => { - const [data, setData] = useState(NULLISH_RESULTS_STATE); + const [data, setData] = useState<{ + [RESULT_TYPES.results]?: object[]; + [RESULT_TYPES.samples]?: object[]; + }>(NULLISH_RESULTS_STATE); const [isLoading, setIsLoading] = useState(NULLISH_RESULTS_STATE); const [error, setError] = useState(NULLISH_RESULTS_STATE); const [filterText, setFilterText] = useState(''); - const [activeTabKey, setActiveTabKey] = useState(RESULT_TYPES.results); + const [activeTabKey, setActiveTabKey] = useState( + RESULT_TYPES.results, + ); useEffect(() => { - const getData = resultType => { + const getData = (resultType: string) => { setIsLoading(prevIsLoading => ({ ...prevIsLoading, [resultType]: true })); return getChartDataRequest({ formData: queryFormData, @@ -99,11 +109,10 @@ export const DataTablesPane = ({ })); }) .catch(response => { - getClientErrorObject(response).then(({ error, statusText }) => { + getClientErrorObject(response).then(({ error, message }) => { setError(prevError => ({ ...prevError, - [resultType]: - error || statusText || t('Sorry, An error occurred'), + [resultType]: error || message || t('Sorry, An error occurred'), })); setIsLoading(prevIsLoading => ({ ...prevIsLoading, @@ -118,12 +127,12 @@ export const DataTablesPane = ({ const filteredData = { [RESULT_TYPES.results]: useFilteredTableData( - data[RESULT_TYPES.results], filterText, + data[RESULT_TYPES.results], ), [RESULT_TYPES.samples]: useFilteredTableData( - data[RESULT_TYPES.samples], filterText, + data[RESULT_TYPES.samples], ), }; @@ -132,11 +141,11 @@ export const DataTablesPane = ({ [RESULT_TYPES.samples]: useTableColumns(data[RESULT_TYPES.samples]), }; - const changeFilterText = event => { + const changeFilterText = (event: React.ChangeEvent) => { setFilterText(event.target.value); }; - const renderDataTable = type => { + const renderDataTable = (type: string) => { if (isLoading[type]) { return ; } @@ -144,7 +153,7 @@ export const DataTablesPane = ({ return
{error[type]}
; } if (data[type]) { - if (data[type].length === 0) { + if (data[type]?.length === 0) { return No data; } return ( @@ -165,7 +174,7 @@ export const DataTablesPane = ({ - + ); diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 884a59d0464df..49aae8b093985 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -210,7 +210,7 @@ const ExploreChartPanel = props => { // dom manipulation hack to get rid of the boostrap theme's body background const standaloneClass = 'background-transparent'; const bodyClasses = document.body.className.split(' '); - if (bodyClasses.indexOf(standaloneClass) === -1) { + if (!bodyClasses.includes(standaloneClass)) { document.body.className += ` ${standaloneClass}`; } return renderChart(); From 227135d4c42a9c9b3f1453493e1423f10578fd6f Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 13:33:04 +0100 Subject: [PATCH 20/33] Fix after rebase --- .../src/explore/components/DataTableControl.tsx | 4 ++-- .../src/explore/components/DisplayQueryButton.jsx | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTableControl.tsx b/superset-frontend/src/explore/components/DataTableControl.tsx index c47b613b222e3..daeb773d5649e 100644 --- a/superset-frontend/src/explore/components/DataTableControl.tsx +++ b/superset-frontend/src/explore/components/DataTableControl.tsx @@ -27,7 +27,7 @@ import { import CopyToClipboard from 'src/components/CopyToClipboard'; import RowCountLabel from './RowCountLabel'; -const CopyButton = styled(Button)` +export const CopyButton = styled(Button)` font-size: ${({ theme }) => theme.typography.sizes.s}px; // needed to override button's first-of-type margin: 0 @@ -36,7 +36,7 @@ const CopyButton = styled(Button)` } i { - padding: 0; + padding: 0 ${({ theme }) => theme.gridUnit}px; } `; diff --git a/superset-frontend/src/explore/components/DisplayQueryButton.jsx b/superset-frontend/src/explore/components/DisplayQueryButton.jsx index f1fe2d94bca9c..1482156098e0f 100644 --- a/superset-frontend/src/explore/components/DisplayQueryButton.jsx +++ b/superset-frontend/src/explore/components/DisplayQueryButton.jsx @@ -27,10 +27,9 @@ import sqlSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql'; import jsonSyntax from 'react-syntax-highlighter/dist/cjs/languages/hljs/json'; import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github'; import { DropdownButton } from 'react-bootstrap'; -import { t } from '@superset-ui/core'; +import { styled, t } from '@superset-ui/core'; import { Menu } from 'src/common/components'; -import Button from 'src/components/Button'; import getClientErrorObject from '../../utils/getClientErrorObject'; import CopyToClipboard from '../../components/CopyToClipboard'; import { getChartDataRequest } from '../../chart/chartAction'; @@ -39,6 +38,7 @@ import Loading from '../../components/Loading'; import ModalTrigger from '../../components/ModalTrigger'; import PropertiesModal from './PropertiesModal'; import { sliceUpdated } from '../actions/exploreActions'; +import { CopyButton } from './DataTableControl'; SyntaxHighlighter.registerLanguage('markdown', markdownSyntax); SyntaxHighlighter.registerLanguage('html', htmlSyntax); @@ -60,6 +60,12 @@ const MENU_KEYS = { DOWNLOAD_AS_IMAGE: 'download_as_image', }; +const CopyButtonViewQuery = styled(CopyButton)` + && { + margin: 0 0 ${({ theme }) => theme.gridUnit}px; + } +`; + export const DisplayQueryButton = props => { const { datasource } = props.latestQueryFormData; @@ -144,7 +150,7 @@ export const DisplayQueryButton = props => { text={query} shouldShowText={false} copyNode={ - + } From e20d4f98690d2a19f43a4f5e11d19e559d424b4c Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 16:14:39 +0100 Subject: [PATCH 21/33] Remove forceRender --- superset-frontend/src/explore/components/DataTablesPane.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index e3cf3da694fb8..e26aaef1a11c6 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -182,7 +182,7 @@ export const DataTablesPane = ({ - + Date: Thu, 3 Dec 2020 19:29:20 +0100 Subject: [PATCH 22/33] Fix big_number test --- .../integration/explore/visualizations/big_number.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/big_number.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/big_number.test.js index 6f6ed8d8e63dc..fb7f15cd6d411 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/big_number.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/big_number.test.js @@ -75,8 +75,8 @@ describe('Visualization > Big Number with Trendline', () => { ...BIG_NUMBER_FORM_DATA, show_trend_line: false, }); - cy.get('.chart-container .header-line'); - cy.get('.chart-container .subheader-line'); - cy.get('.chart-container svg').should('not.exist'); + cy.get('[data-test="chart-container"] .header-line'); + cy.get('[data-test="chart-container"] .subheader-line'); + cy.get('[data-test="chart-container"] svg').should('not.exist'); }); }); From 03c0c3474ceedc843aa826e8f9c62926b133d6d4 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 19:53:20 +0100 Subject: [PATCH 23/33] Delay making request until panel is opened --- .../src/explore/components/DataTablesPane.tsx | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index e26aaef1a11c6..6d308ab8e9a9d 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -86,6 +86,12 @@ export const DataTablesPane = ({ const [activeTabKey, setActiveTabKey] = useState( RESULT_TYPES.results, ); + const [isRequestPending, setIsRequestPending] = useState(false); + const [panelOpen, setPanelOpen] = useState(false); + + useEffect(() => { + setIsRequestPending(true); + }, [queryFormData]); useEffect(() => { const getData = (resultType: string) => { @@ -121,9 +127,12 @@ export const DataTablesPane = ({ }); }); }; - getData(RESULT_TYPES.results); - getData(RESULT_TYPES.samples); - }, [queryFormData]); + if (panelOpen && isRequestPending) { + setIsRequestPending(false); + getData(RESULT_TYPES.results); + getData(RESULT_TYPES.samples); + } + }, [queryFormData, panelOpen, isRequestPending]); const filteredData = { [RESULT_TYPES.results]: useFilteredTableData( @@ -178,10 +187,15 @@ export const DataTablesPane = ({ ); + const handleCollapseChange = (openPanelName: string) => { + onCollapseChange(openPanelName); + setPanelOpen(!!openPanelName); + }; + return ( - + Date: Thu, 3 Dec 2020 20:04:38 +0100 Subject: [PATCH 24/33] White background in south panel --- .../src/explore/components/DataTablesPane.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index 6d308ab8e9a9d..a887981d667c1 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -53,8 +53,14 @@ const TableControlsWrapper = styled.div` `; const SouthPane = styled.div` - background-color: ${({ theme }) => theme.colors.grayscale.light5}; - z-index: 1; + position: relative; +`; + +const SouthPaneBackground = styled.div` + position: absolute; + height: 100%; + width: 100%; + background: ${({ theme }) => theme.colors.grayscale.light5}; `; const TabsWrapper = styled.div<{ contentHeight: number }>` @@ -165,6 +171,7 @@ export const DataTablesPane = ({ if (data[type]?.length === 0) { return No data; } + console.log(filteredData[type]); return ( + From c897e74eb313e4cdb1dde6a31719ebd99f65a9e0 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 20:19:21 +0100 Subject: [PATCH 25/33] fixup! White background in south panel --- .../src/explore/components/DataTablesPane.tsx | 4 +++- .../src/explore/components/ExploreChartPanel.jsx | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index a887981d667c1..950f8cec9f5d6 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -77,10 +77,12 @@ export const DataTablesPane = ({ queryFormData, tableSectionHeight, onCollapseChange, + displayBackground, }: { queryFormData: object; tableSectionHeight: number; onCollapseChange: (openPanelName: string) => void; + displayBackground: boolean; }) => { const [data, setData] = useState<{ [RESULT_TYPES.results]?: object[]; @@ -201,7 +203,7 @@ export const DataTablesPane = ({ return ( - + {displayBackground && } diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 49aae8b093985..0d20bb58aa311 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -138,6 +138,9 @@ const ExploreChartPanel = props => { const [tableSectionHeight, setTableSectionHeight] = useState( calcSectionHeight(INITIAL_SIZES[1]), ); + const [displaySouthPaneBackground, setDisplaySouthPaneBackground] = useState( + false, + ); useEffect(() => { const calcHeaderSize = debounce(() => { @@ -150,6 +153,15 @@ const ExploreChartPanel = props => { return () => document.removeEventListener('resize', calcHeaderSize); }, [props.standalone]); + const onDragStart = () => { + setDisplaySouthPaneBackground(true); + }; + + const onDragEnd = sizes => { + recalcPanelSizes(sizes); + setDisplaySouthPaneBackground(false); + }; + const recalcPanelSizes = ([northPercent, southPercent]) => { setChartSectionHeight( calcSectionHeight(northPercent) - CHART_PANEL_PADDING, @@ -251,7 +263,8 @@ const ExploreChartPanel = props => { minSize={MIN_SIZES} direction="vertical" gutterSize={EXPLORE_GUTTER_HEIGHT} - onDragEnd={recalcPanelSizes} + onDragStart={onDragStart} + onDragEnd={onDragEnd} elementStyle={elementStyle} >
{renderChart()}
@@ -259,6 +272,7 @@ const ExploreChartPanel = props => { queryFormData={props.chart.latestQueryFormData} tableSectionHeight={tableSectionHeight} onCollapseChange={onCollapseChange} + displayBackground={displaySouthPaneBackground} />
From 28693770b2ecc2b78c70a5b26322b3e9942d0f8c Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 22:24:10 +0100 Subject: [PATCH 26/33] Lint fix --- .../src/explore/components/ExploreChartPanel.jsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 0d20bb58aa311..3be123ffc5a20 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -153,6 +153,13 @@ const ExploreChartPanel = props => { return () => document.removeEventListener('resize', calcHeaderSize); }, [props.standalone]); + const recalcPanelSizes = ([northPercent, southPercent]) => { + setChartSectionHeight( + calcSectionHeight(northPercent) - CHART_PANEL_PADDING, + ); + setTableSectionHeight(calcSectionHeight(southPercent)); + }; + const onDragStart = () => { setDisplaySouthPaneBackground(true); }; @@ -162,12 +169,6 @@ const ExploreChartPanel = props => { setDisplaySouthPaneBackground(false); }; - const recalcPanelSizes = ([northPercent, southPercent]) => { - setChartSectionHeight( - calcSectionHeight(northPercent) - CHART_PANEL_PADDING, - ); - setTableSectionHeight(calcSectionHeight(southPercent)); - }; const onCollapseChange = openPanelName => { let splitSizes; From 7ad34158225013103a84e427dc50cbffc27cebdd Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Thu, 3 Dec 2020 22:35:52 +0100 Subject: [PATCH 27/33] Lint fix --- superset-frontend/src/explore/components/ExploreChartPanel.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 3be123ffc5a20..5693a8a5cf2f3 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -169,7 +169,6 @@ const ExploreChartPanel = props => { setDisplaySouthPaneBackground(false); }; - const onCollapseChange = openPanelName => { let splitSizes; if (!openPanelName) { From f7e76f3c09c1606935e429fdbbaad6e1790499cb Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Fri, 4 Dec 2020 10:14:31 +0100 Subject: [PATCH 28/33] Remove redundant prop types --- .../src/explore/components/DataTablesPane.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index 950f8cec9f5d6..5f5540191dec2 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -17,7 +17,6 @@ * under the License. */ import React, { useEffect, useState } from 'react'; -import PropTypes from 'prop-types'; import { styled, t } from '@superset-ui/core'; import { Collapse } from 'src/common/components'; import Tabs from 'src/common/components/Tabs'; @@ -226,9 +225,3 @@ export const DataTablesPane = ({ ); }; - -DataTablesPane.propTypes = { - tableSectionHeight: PropTypes.number, - queryFormData: PropTypes.object, - onCollapseChange: PropTypes.func, -}; From 689c16a768058d6c614100bf31b05f31feefd0d2 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Fri, 4 Dec 2020 16:28:04 +0100 Subject: [PATCH 29/33] Remove console log --- superset-frontend/src/explore/components/DataTablesPane.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index 5f5540191dec2..1ec5c6339bcbd 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -172,7 +172,6 @@ export const DataTablesPane = ({ if (data[type]?.length === 0) { return No data; } - console.log(filteredData[type]); return ( Date: Fri, 4 Dec 2020 16:54:29 +0100 Subject: [PATCH 30/33] Delay loading samples until user switches tab --- .../src/explore/components/DataTablesPane.tsx | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index 1ec5c6339bcbd..929517fe6427f 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { styled, t } from '@superset-ui/core'; import { Collapse } from 'src/common/components'; import Tabs from 'src/common/components/Tabs'; @@ -93,15 +93,14 @@ export const DataTablesPane = ({ const [activeTabKey, setActiveTabKey] = useState( RESULT_TYPES.results, ); - const [isRequestPending, setIsRequestPending] = useState(false); + const [isRequestPending, setIsRequestPending] = useState<{ + [RESULT_TYPES.results]?: boolean; + [RESULT_TYPES.samples]?: boolean; + }>(NULLISH_RESULTS_STATE); const [panelOpen, setPanelOpen] = useState(false); - useEffect(() => { - setIsRequestPending(true); - }, [queryFormData]); - - useEffect(() => { - const getData = (resultType: string) => { + const getData = useCallback( + (resultType: string) => { setIsLoading(prevIsLoading => ({ ...prevIsLoading, [resultType]: true })); return getChartDataRequest({ formData: queryFormData, @@ -133,13 +132,37 @@ export const DataTablesPane = ({ })); }); }); - }; - if (panelOpen && isRequestPending) { - setIsRequestPending(false); + }, + [queryFormData], + ); + + useEffect(() => { + setIsRequestPending({ + [RESULT_TYPES.results]: true, + [RESULT_TYPES.samples]: true, + }); + }, [queryFormData]); + + useEffect(() => { + if (panelOpen && isRequestPending[RESULT_TYPES.results]) { + setIsRequestPending(prevState => ({ + ...prevState, + [RESULT_TYPES.results]: false, + })); getData(RESULT_TYPES.results); + } + if ( + panelOpen && + isRequestPending[RESULT_TYPES.samples] && + activeTabKey === RESULT_TYPES.samples + ) { + setIsRequestPending(prevState => ({ + ...prevState, + [RESULT_TYPES.samples]: false, + })); getData(RESULT_TYPES.samples); } - }, [queryFormData, panelOpen, isRequestPending]); + }, [panelOpen, isRequestPending, getData, activeTabKey]); const filteredData = { [RESULT_TYPES.results]: useFilteredTableData( From 4e4da812f2773ccc87d0e1529bac41220162be6e Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Fri, 4 Dec 2020 19:22:16 +0100 Subject: [PATCH 31/33] Add debounce to filter input --- .../explore/components/DataTableControl.tsx | 26 +++++++++++-------- .../src/explore/components/DataTablesPane.tsx | 6 +---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTableControl.tsx b/superset-frontend/src/explore/components/DataTableControl.tsx index daeb773d5649e..5b7f12acd1a54 100644 --- a/superset-frontend/src/explore/components/DataTableControl.tsx +++ b/superset-frontend/src/explore/components/DataTableControl.tsx @@ -19,6 +19,7 @@ import React, { useMemo } from 'react'; import { styled, t } from '@superset-ui/core'; import { FormControl } from 'react-bootstrap'; +import debounce from 'lodash/debounce'; import Button from 'src/components/Button'; import { applyFormattingToTabularData, @@ -53,19 +54,22 @@ export const CopyToClipboardButton = ({ data }: { data: object }) => ( ); export const FilterInput = ({ - filterText, onChangeHandler, }: { - filterText: string; - onChangeHandler(event: React.ChangeEvent): void; -}) => ( - onChangeHandler(event as any)} - /> -); + onChangeHandler(filterText: string): void; +}) => { + const debouncedChangeHandler = debounce(onChangeHandler, 500); + return ( + { + const filterText = event.target.value; + debouncedChangeHandler(filterText); + }} + /> + ); +}; export const RowCount = ({ data }: { data: object[] }) => ( diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index 929517fe6427f..6848ad2220848 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -180,10 +180,6 @@ export const DataTablesPane = ({ [RESULT_TYPES.samples]: useTableColumns(data[RESULT_TYPES.samples]), }; - const changeFilterText = (event: React.ChangeEvent) => { - setFilterText(event.target.value); - }; - const renderDataTable = (type: string) => { if (isLoading[type]) { return ; @@ -213,7 +209,7 @@ export const DataTablesPane = ({ - + ); From 62bd8f43ba1722d71342f9a7a7444460f2d51291 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Fri, 4 Dec 2020 20:21:42 +0100 Subject: [PATCH 32/33] Use gridUnit for gutter sizes --- .../explore/components/ExploreChartPanel.jsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/superset-frontend/src/explore/components/ExploreChartPanel.jsx b/superset-frontend/src/explore/components/ExploreChartPanel.jsx index 5693a8a5cf2f3..e90f4fe6df7dc 100644 --- a/superset-frontend/src/explore/components/ExploreChartPanel.jsx +++ b/superset-frontend/src/explore/components/ExploreChartPanel.jsx @@ -20,7 +20,7 @@ import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import Split from 'react-split'; import { ParentSize } from '@vx/responsive'; -import { styled } from '@superset-ui/core'; +import { styled, useTheme } from '@superset-ui/core'; import debounce from 'lodash/debounce'; import { chartPropShape } from 'src/dashboard/util/propShapes'; import ChartContainer from 'src/chart/ChartContainer'; @@ -52,8 +52,8 @@ const propTypes = { triggerRender: PropTypes.bool, }; -const EXPLORE_GUTTER_HEIGHT = 5; -const EXPLORE_GUTTER_MARGIN = 3; +const GUTTER_SIZE_FACTOR = 1.25; + const CHART_PANEL_PADDING = 30; const INITIAL_SIZES = [90, 10]; @@ -76,7 +76,7 @@ const Styles = styled.div` border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; border-bottom: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; width: ${({ theme }) => theme.gridUnit * 9}px; - margin: ${EXPLORE_GUTTER_MARGIN}px auto; + margin: ${({ theme }) => theme.gridUnit * GUTTER_SIZE_FACTOR}px auto; } .gutter.gutter-vertical { @@ -120,6 +120,10 @@ const Styles = styled.div` `; const ExploreChartPanel = props => { + const theme = useTheme(); + const gutterMargin = theme.gridUnit * GUTTER_SIZE_FACTOR; + const gutterHeight = theme.gridUnit * GUTTER_SIZE_FACTOR; + const panelHeadingRef = useRef(null); const [headerHeight, setHeaderHeight] = useState(props.standalone ? 0 : 50); const [splitSizes, setSplitSizes] = useState(INITIAL_SIZES); @@ -127,8 +131,7 @@ const ExploreChartPanel = props => { const calcSectionHeight = percent => { const containerHeight = parseInt(props.height, 10) - headerHeight - 30; return ( - (containerHeight * percent) / 100 - - (EXPLORE_GUTTER_HEIGHT / 2 + EXPLORE_GUTTER_MARGIN) + (containerHeight * percent) / 100 - (gutterHeight / 2 + gutterMargin) ); }; @@ -247,9 +250,7 @@ const ExploreChartPanel = props => { const elementStyle = (dimension, elementSize, gutterSize) => { return { - [dimension]: `calc(${elementSize}% - ${ - gutterSize + EXPLORE_GUTTER_MARGIN - }px)`, + [dimension]: `calc(${elementSize}% - ${gutterSize + gutterMargin}px)`, }; }; @@ -262,7 +263,7 @@ const ExploreChartPanel = props => { sizes={splitSizes} minSize={MIN_SIZES} direction="vertical" - gutterSize={EXPLORE_GUTTER_HEIGHT} + gutterSize={gutterHeight} onDragStart={onDragStart} onDragEnd={onDragEnd} elementStyle={elementStyle} From 585844fd81a95a99a74509277ab639df54c71d27 Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Fri, 4 Dec 2020 22:09:30 +0100 Subject: [PATCH 33/33] Change types object to Record --- .../src/explore/components/DataTableControl.tsx | 17 ++++++++++++----- .../src/explore/components/DataTablesPane.tsx | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/superset-frontend/src/explore/components/DataTableControl.tsx b/superset-frontend/src/explore/components/DataTableControl.tsx index 5b7f12acd1a54..8768e31bfd627 100644 --- a/superset-frontend/src/explore/components/DataTableControl.tsx +++ b/superset-frontend/src/explore/components/DataTableControl.tsx @@ -41,7 +41,11 @@ export const CopyButton = styled(Button)` } `; -export const CopyToClipboardButton = ({ data }: { data: object }) => ( +export const CopyToClipboardButton = ({ + data, +}: { + data?: Record; +}) => ( ( +export const RowCount = ({ data }: { data?: Record[] }) => ( ); -export const useFilteredTableData = (filterText: string, data?: object[]) => +export const useFilteredTableData = ( + filterText: string, + data?: Record[], +) => useMemo(() => { if (!data?.length) { return []; } const formattedData = applyFormattingToTabularData(data); - return formattedData.filter((row: object) => + return formattedData.filter((row: Record) => Object.values(row).some(value => value.toString().toLowerCase().includes(filterText.toLowerCase()), ), ); }, [data, filterText]); -export const useTableColumns = (data?: object[]) => +export const useTableColumns = (data?: Record[]) => useMemo( () => data?.length diff --git a/superset-frontend/src/explore/components/DataTablesPane.tsx b/superset-frontend/src/explore/components/DataTablesPane.tsx index 6848ad2220848..b1bc9081db6b1 100644 --- a/superset-frontend/src/explore/components/DataTablesPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane.tsx @@ -78,14 +78,14 @@ export const DataTablesPane = ({ onCollapseChange, displayBackground, }: { - queryFormData: object; + queryFormData: Record; tableSectionHeight: number; onCollapseChange: (openPanelName: string) => void; displayBackground: boolean; }) => { const [data, setData] = useState<{ - [RESULT_TYPES.results]?: object[]; - [RESULT_TYPES.samples]?: object[]; + [RESULT_TYPES.results]?: Record[]; + [RESULT_TYPES.samples]?: Record[]; }>(NULLISH_RESULTS_STATE); const [isLoading, setIsLoading] = useState(NULLISH_RESULTS_STATE); const [error, setError] = useState(NULLISH_RESULTS_STATE);