refactor: Convert TableElement to TypeScript (#14978)

* Convert TableElement to typescript

* Change type names to better match naming conventions in other files

* Fix import order and update tests on TableElement

* Remove defaultProps

* Destructure the props

* Use Rest and Spread syntax to condense props destructuring

* Fix TypeScript errors and add comment to explain antd props and types weirdness

* Remove comment, add consistency with other files, and use method chaining to make more concise

Co-authored-by: Corbin Robb <corbin@Corbins-MacBook-Pro.local>
This commit is contained in:
Corbin Robb 2021-06-15 14:29:45 -06:00 committed by GitHub
parent 7dc0cee5be
commit b179863e25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 61 deletions

View File

@ -55,7 +55,7 @@ describe('TableElement', () => {
},
},
);
expect(wrapper.find(IconTooltip)).toHaveLength(5);
expect(wrapper.find(IconTooltip)).toHaveLength(4);
});
it('has 14 columns', () => {
const wrapper = shallow(<TableElement {...mockedProps} />);
@ -112,20 +112,20 @@ describe('TableElement', () => {
},
);
expect(
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-alpha-asc'),
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-alpha-asc'),
).toEqual(true);
expect(
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-numeric-asc'),
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-numeric-asc'),
).toEqual(false);
wrapper.find('.header-container').hostNodes().simulate('click');
expect(wrapper.find(ColumnElement).first().props().column.name).toBe('id');
wrapper.find('.header-container').simulate('mouseEnter');
wrapper.find('.sort-cols').hostNodes().simulate('click');
expect(
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-numeric-asc'),
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-numeric-asc'),
).toEqual(true);
expect(
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-alpha-asc'),
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-alpha-asc'),
).toEqual(false);
expect(wrapper.find(ColumnElement).first().props().column.name).toBe(
'active',

View File

@ -21,8 +21,10 @@ import PropTypes from 'prop-types';
import Button from 'src/components/Button';
import { t, styled, css } from '@superset-ui/core';
import Collapse from 'src/components/Collapse';
import Icons from 'src/components/Icons';
import TableElement from './TableElement';
import TableSelector from '../../components/TableSelector';
import { IconTooltip } from '../../components/IconTooltip';
const propTypes = {
queryEditor: PropTypes.object.isRequired,
@ -134,6 +136,23 @@ export default class SqlEditorLeftBar extends React.PureComponent {
this.props.actions.addTable(this.props.queryEditor, tableName, schemaName);
}
renderExpandIconWithTooltip = ({ isActive }) => (
<IconTooltip
css={css`
transform: rotate(90deg);
`}
aria-label="Collapse"
tooltip={t(`${isActive ? 'Collapse' : 'Expand'} table preview`)}
>
<Icons.RightOutlined
iconSize="s"
css={css`
transform: ${isActive ? 'rotateY(180deg)' : ''};
`}
/>
</IconTooltip>
);
render() {
const shouldShowReset = window.location.search === '?reset=1';
const tableMetaDataHeight = this.props.height - 130; // 130 is the height of the selects above
@ -184,6 +203,7 @@ export default class SqlEditorLeftBar extends React.PureComponent {
expandIconPosition="right"
ghost
onChange={this.onToggleTable}
expandIcon={this.renderExpandIconWithTooltip}
>
{this.props.tables.map(table => (
<TableElement

View File

@ -17,7 +17,6 @@
* under the License.
*/
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import Collapse from 'src/components/Collapse';
import Card from 'src/components/Card';
import ButtonGroup from 'src/components/ButtonGroup';
@ -25,23 +24,41 @@ import { t, styled } from '@superset-ui/core';
import { debounce } from 'lodash';
import { Tooltip } from 'src/components/Tooltip';
import Icons from 'src/components/Icons';
import CopyToClipboard from '../../components/CopyToClipboard';
import { IconTooltip } from '../../components/IconTooltip';
import ColumnElement from './ColumnElement';
import ColumnElement, { ColumnKeyTypeType } from './ColumnElement';
import ShowSQL from './ShowSQL';
import ModalTrigger from '../../components/ModalTrigger';
import Loading from '../../components/Loading';
const propTypes = {
table: PropTypes.object,
actions: PropTypes.object,
};
interface Column {
name: string;
keys?: { type: ColumnKeyTypeType }[];
type: string;
}
const defaultProps = {
actions: {},
table: null,
};
interface Table {
id: string;
name: string;
partitions?: {
partitionQuery: string;
latest: object[];
};
indexes?: object[];
selectStar?: string;
view?: string;
isMetadataLoading: boolean;
isExtraMetadataLoading: boolean;
columns: Column[];
}
interface TableElementProps {
table: Table;
actions: {
removeDataPreview: (table: Table) => void;
removeTable: (table: Table) => void;
};
}
const StyledSpan = styled.span`
color: ${({ theme }) => theme.colors.primary.dark1};
@ -53,16 +70,14 @@ const StyledSpan = styled.span`
const Fade = styled.div`
transition: all ${({ theme }) => theme.transitionTiming}s;
opacity: ${props => (props.hovered ? 1 : 0)};
opacity: ${(props: { hovered: boolean }) => (props.hovered ? 1 : 0)};
`;
const TableElement = props => {
const TableElement = ({ table, actions, ...props }: TableElementProps) => {
const [sortColumns, setSortColumns] = useState(false);
const [hovered, setHovered] = useState(false);
const { table, actions, isActive } = props;
const setHover = hovered => {
const setHover = (hovered: boolean) => {
debounce(() => setHovered(hovered), 100)();
};
@ -92,10 +107,10 @@ const TableElement = props => {
/>
);
}
let latest = Object.entries(table.partitions?.latest || []).map(
([key, value]) => `${key}=${value}`,
);
latest = latest.join('/');
const latest = Object.entries(table.partitions?.latest || [])
.map(([key, value]) => `${key}=${value}`)
.join('/');
header = (
<Card size="small">
<div>
@ -142,9 +157,9 @@ const TableElement = props => {
}
onClick={toggleSortColumns}
tooltip={
!sortColumns
? t('Sort columns alphabetically')
: t('Original table column order')
sortColumns
? t('Original table column order')
: t('Sort columns alphabetically')
}
/>
{table.selectStar && (
@ -216,16 +231,10 @@ const TableElement = props => {
if (table.columns) {
cols = table.columns.slice();
if (sortColumns) {
cols.sort((a, b) => {
cols.sort((a: Column, b: Column) => {
const colA = a.name.toUpperCase();
const colB = b.name.toUpperCase();
if (colA < colB) {
return -1;
}
if (colA > colB) {
return 1;
}
return 0;
return colA < colB ? -1 : colA > colB ? 1 : 0;
});
}
}
@ -247,41 +256,17 @@ const TableElement = props => {
return metadata;
};
const collapseExpandIcon = () => (
<IconTooltip
style={{
position: 'fixed',
right: '16px',
left: 'auto',
fontSize: '12px',
transform: 'rotate(90deg)',
display: 'flex',
alignItems: 'center',
}}
aria-label="Collapse"
tooltip={t(`${isActive ? 'Collapse' : 'Expand'} table preview`)}
>
<Icons.RightOutlined
iconSize="s"
style={isActive ? { transform: 'rotateY(180deg)' } : null}
/>
</IconTooltip>
);
return (
<Collapse.Panel
{...props}
key={table.id}
header={renderHeader()}
className="TableElement"
forceRender
expandIcon={collapseExpandIcon}
>
{renderBody()}
</Collapse.Panel>
);
};
TableElement.propTypes = propTypes;
TableElement.defaultProps = defaultProps;
export default TableElement;