mirror of
https://github.com/apache/superset.git
synced 2024-09-12 08:39:45 -04:00
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:
parent
7dc0cee5be
commit
b179863e25
@ -55,7 +55,7 @@ describe('TableElement', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(wrapper.find(IconTooltip)).toHaveLength(5);
|
expect(wrapper.find(IconTooltip)).toHaveLength(4);
|
||||||
});
|
});
|
||||||
it('has 14 columns', () => {
|
it('has 14 columns', () => {
|
||||||
const wrapper = shallow(<TableElement {...mockedProps} />);
|
const wrapper = shallow(<TableElement {...mockedProps} />);
|
||||||
@ -112,20 +112,20 @@ describe('TableElement', () => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-alpha-asc'),
|
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-alpha-asc'),
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
expect(
|
expect(
|
||||||
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-numeric-asc'),
|
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-numeric-asc'),
|
||||||
).toEqual(false);
|
).toEqual(false);
|
||||||
wrapper.find('.header-container').hostNodes().simulate('click');
|
wrapper.find('.header-container').hostNodes().simulate('click');
|
||||||
expect(wrapper.find(ColumnElement).first().props().column.name).toBe('id');
|
expect(wrapper.find(ColumnElement).first().props().column.name).toBe('id');
|
||||||
wrapper.find('.header-container').simulate('mouseEnter');
|
wrapper.find('.header-container').simulate('mouseEnter');
|
||||||
wrapper.find('.sort-cols').hostNodes().simulate('click');
|
wrapper.find('.sort-cols').hostNodes().simulate('click');
|
||||||
expect(
|
expect(
|
||||||
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-numeric-asc'),
|
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-numeric-asc'),
|
||||||
).toEqual(true);
|
).toEqual(true);
|
||||||
expect(
|
expect(
|
||||||
wrapper.find(IconTooltip).at(2).hasClass('fa-sort-alpha-asc'),
|
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-alpha-asc'),
|
||||||
).toEqual(false);
|
).toEqual(false);
|
||||||
expect(wrapper.find(ColumnElement).first().props().column.name).toBe(
|
expect(wrapper.find(ColumnElement).first().props().column.name).toBe(
|
||||||
'active',
|
'active',
|
||||||
|
@ -21,8 +21,10 @@ import PropTypes from 'prop-types';
|
|||||||
import Button from 'src/components/Button';
|
import Button from 'src/components/Button';
|
||||||
import { t, styled, css } from '@superset-ui/core';
|
import { t, styled, css } from '@superset-ui/core';
|
||||||
import Collapse from 'src/components/Collapse';
|
import Collapse from 'src/components/Collapse';
|
||||||
|
import Icons from 'src/components/Icons';
|
||||||
import TableElement from './TableElement';
|
import TableElement from './TableElement';
|
||||||
import TableSelector from '../../components/TableSelector';
|
import TableSelector from '../../components/TableSelector';
|
||||||
|
import { IconTooltip } from '../../components/IconTooltip';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
queryEditor: PropTypes.object.isRequired,
|
queryEditor: PropTypes.object.isRequired,
|
||||||
@ -134,6 +136,23 @@ export default class SqlEditorLeftBar extends React.PureComponent {
|
|||||||
this.props.actions.addTable(this.props.queryEditor, tableName, schemaName);
|
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() {
|
render() {
|
||||||
const shouldShowReset = window.location.search === '?reset=1';
|
const shouldShowReset = window.location.search === '?reset=1';
|
||||||
const tableMetaDataHeight = this.props.height - 130; // 130 is the height of the selects above
|
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"
|
expandIconPosition="right"
|
||||||
ghost
|
ghost
|
||||||
onChange={this.onToggleTable}
|
onChange={this.onToggleTable}
|
||||||
|
expandIcon={this.renderExpandIconWithTooltip}
|
||||||
>
|
>
|
||||||
{this.props.tables.map(table => (
|
{this.props.tables.map(table => (
|
||||||
<TableElement
|
<TableElement
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Collapse from 'src/components/Collapse';
|
import Collapse from 'src/components/Collapse';
|
||||||
import Card from 'src/components/Card';
|
import Card from 'src/components/Card';
|
||||||
import ButtonGroup from 'src/components/ButtonGroup';
|
import ButtonGroup from 'src/components/ButtonGroup';
|
||||||
@ -25,23 +24,41 @@ import { t, styled } from '@superset-ui/core';
|
|||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
import { Tooltip } from 'src/components/Tooltip';
|
import { Tooltip } from 'src/components/Tooltip';
|
||||||
import Icons from 'src/components/Icons';
|
|
||||||
import CopyToClipboard from '../../components/CopyToClipboard';
|
import CopyToClipboard from '../../components/CopyToClipboard';
|
||||||
import { IconTooltip } from '../../components/IconTooltip';
|
import { IconTooltip } from '../../components/IconTooltip';
|
||||||
import ColumnElement from './ColumnElement';
|
import ColumnElement, { ColumnKeyTypeType } from './ColumnElement';
|
||||||
import ShowSQL from './ShowSQL';
|
import ShowSQL from './ShowSQL';
|
||||||
import ModalTrigger from '../../components/ModalTrigger';
|
import ModalTrigger from '../../components/ModalTrigger';
|
||||||
import Loading from '../../components/Loading';
|
import Loading from '../../components/Loading';
|
||||||
|
|
||||||
const propTypes = {
|
interface Column {
|
||||||
table: PropTypes.object,
|
name: string;
|
||||||
actions: PropTypes.object,
|
keys?: { type: ColumnKeyTypeType }[];
|
||||||
};
|
type: string;
|
||||||
|
}
|
||||||
|
|
||||||
const defaultProps = {
|
interface Table {
|
||||||
actions: {},
|
id: string;
|
||||||
table: null,
|
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`
|
const StyledSpan = styled.span`
|
||||||
color: ${({ theme }) => theme.colors.primary.dark1};
|
color: ${({ theme }) => theme.colors.primary.dark1};
|
||||||
@ -53,16 +70,14 @@ const StyledSpan = styled.span`
|
|||||||
|
|
||||||
const Fade = styled.div`
|
const Fade = styled.div`
|
||||||
transition: all ${({ theme }) => theme.transitionTiming}s;
|
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 [sortColumns, setSortColumns] = useState(false);
|
||||||
const [hovered, setHovered] = useState(false);
|
const [hovered, setHovered] = useState(false);
|
||||||
|
|
||||||
const { table, actions, isActive } = props;
|
const setHover = (hovered: boolean) => {
|
||||||
|
|
||||||
const setHover = hovered => {
|
|
||||||
debounce(() => setHovered(hovered), 100)();
|
debounce(() => setHovered(hovered), 100)();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,10 +107,10 @@ const TableElement = props => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let latest = Object.entries(table.partitions?.latest || []).map(
|
const latest = Object.entries(table.partitions?.latest || [])
|
||||||
([key, value]) => `${key}=${value}`,
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
);
|
.join('/');
|
||||||
latest = latest.join('/');
|
|
||||||
header = (
|
header = (
|
||||||
<Card size="small">
|
<Card size="small">
|
||||||
<div>
|
<div>
|
||||||
@ -142,9 +157,9 @@ const TableElement = props => {
|
|||||||
}
|
}
|
||||||
onClick={toggleSortColumns}
|
onClick={toggleSortColumns}
|
||||||
tooltip={
|
tooltip={
|
||||||
!sortColumns
|
sortColumns
|
||||||
? t('Sort columns alphabetically')
|
? t('Original table column order')
|
||||||
: t('Original table column order')
|
: t('Sort columns alphabetically')
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{table.selectStar && (
|
{table.selectStar && (
|
||||||
@ -216,16 +231,10 @@ const TableElement = props => {
|
|||||||
if (table.columns) {
|
if (table.columns) {
|
||||||
cols = table.columns.slice();
|
cols = table.columns.slice();
|
||||||
if (sortColumns) {
|
if (sortColumns) {
|
||||||
cols.sort((a, b) => {
|
cols.sort((a: Column, b: Column) => {
|
||||||
const colA = a.name.toUpperCase();
|
const colA = a.name.toUpperCase();
|
||||||
const colB = b.name.toUpperCase();
|
const colB = b.name.toUpperCase();
|
||||||
if (colA < colB) {
|
return colA < colB ? -1 : colA > colB ? 1 : 0;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (colA > colB) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,41 +256,17 @@ const TableElement = props => {
|
|||||||
return metadata;
|
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 (
|
return (
|
||||||
<Collapse.Panel
|
<Collapse.Panel
|
||||||
{...props}
|
{...props}
|
||||||
|
key={table.id}
|
||||||
header={renderHeader()}
|
header={renderHeader()}
|
||||||
className="TableElement"
|
className="TableElement"
|
||||||
forceRender
|
forceRender
|
||||||
expandIcon={collapseExpandIcon}
|
|
||||||
>
|
>
|
||||||
{renderBody()}
|
{renderBody()}
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
TableElement.propTypes = propTypes;
|
|
||||||
TableElement.defaultProps = defaultProps;
|
|
||||||
|
|
||||||
export default TableElement;
|
export default TableElement;
|
Loading…
Reference in New Issue
Block a user