Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Convert TableElement.jsx component from class to functional with hooks #14830

Merged
16 changes: 12 additions & 4 deletions superset-frontend/spec/javascripts/sqllab/TableElement_spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,11 @@ describe('TableElement', () => {
},
},
);
expect(wrapper.find(TableElement).state().hovered).toBe(false);
expect(wrapper.find('[data-test="fade"]').first().props().hovered).toBe(
false,
);
wrapper.find('.header-container').hostNodes().simulate('mouseEnter');
await waitForComponentToPaint(wrapper, 300);
expect(wrapper.find(TableElement).state().hovered).toBe(true);
expect(wrapper.find('[data-test="fade"]').first().props().hovered).toBe(
true,
);
Expand All @@ -111,12 +109,22 @@ describe('TableElement', () => {
},
},
);
expect(wrapper.find(TableElement).state().sortColumns).toBe(false);
expect(
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-alpha-asc'),
).toEqual(true);
expect(
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(TableElement).state().sortColumns).toBe(true);
expect(
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-numeric-asc'),
).toEqual(true);
expect(
wrapper.find(IconTooltip).at(1).hasClass('fa-sort-alpha-asc'),
).toEqual(false);
expect(wrapper.find(ColumnElement).first().props().column.name).toBe(
'active',
);
Expand Down
118 changes: 53 additions & 65 deletions superset-frontend/src/SqlLab/components/TableElement.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import React from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import Collapse from 'src/components/Collapse';
import Card from 'src/components/Card';
Expand Down Expand Up @@ -56,44 +56,37 @@ const Fade = styled.div`
opacity: ${props => (props.hovered ? 1 : 0)};
`;

class TableElement extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
sortColumns: false,
hovered: false,
};
this.toggleSortColumns = this.toggleSortColumns.bind(this);
this.removeTable = this.removeTable.bind(this);
this.setHover = debounce(this.setHover.bind(this), 100);
}
const TableElement = props => {
const [sortColumns, setSortColumns] = useState(false);
const [hovered, setHovered] = useState(false);

setHover(hovered) {
this.setState({ hovered });
}
const { table, actions } = props;

const setHover = hovered => {
debounce(() => setHovered(hovered), 100)();
};

popSelectStar() {
const popSelectStar = () => {
const qe = {
id: shortid.generate(),
title: this.props.table.name,
dbId: this.props.table.dbId,
title: table.name,
dbId: table.dbId,
autorun: true,
sql: this.props.table.selectStar,
sql: table.selectStar,
};
this.props.actions.addQueryEditor(qe);
}
actions.addQueryEditor(qe);
};

removeTable() {
this.props.actions.removeDataPreview(this.props.table);
this.props.actions.removeTable(this.props.table);
}
const removeTable = () => {
actions.removeDataPreview(table);
actions.removeTable(table);
};

toggleSortColumns() {
this.setState(prevState => ({ sortColumns: !prevState.sortColumns }));
}
const toggleSortColumns = () => {
setSortColumns(prevState => !prevState);
};

renderWell() {
const { table } = this.props;
const renderWell = () => {
let header;
if (table.partitions) {
let partitionQuery;
Expand Down Expand Up @@ -126,11 +119,10 @@ class TableElement extends React.PureComponent {
);
}
return header;
}
};

renderControls() {
const renderControls = () => {
let keyLink;
const { table } = this.props;
if (table.indexes && table.indexes.length > 0) {
corbinrobb marked this conversation as resolved.
Show resolved Hide resolved
keyLink = (
<ModalTrigger
Expand All @@ -156,12 +148,12 @@ class TableElement extends React.PureComponent {
{keyLink}
<IconTooltip
className={
`fa fa-sort-${!this.state.sortColumns ? 'alpha' : 'numeric'}-asc ` +
`fa fa-sort-${!sortColumns ? 'alpha' : 'numeric'}-asc ` +
corbinrobb marked this conversation as resolved.
Show resolved Hide resolved
'pull-left sort-cols m-l-2 pointer'
}
onClick={this.toggleSortColumns}
onClick={toggleSortColumns}
tooltip={
!this.state.sortColumns
!sortColumns
? t('Sort columns alphabetically')
: t('Original table column order')
}
Expand All @@ -187,20 +179,19 @@ class TableElement extends React.PureComponent {
)}
<IconTooltip
className="fa fa-times table-remove pull-left m-l-2 pointer"
onClick={this.removeTable}
onClick={removeTable}
tooltip={t('Remove table preview')}
/>
</ButtonGroup>
);
}
};

renderHeader() {
const { table } = this.props;
const renderHeader = () => {
return (
<div
className="clearfix header-container"
onMouseEnter={() => this.setHover(true)}
onMouseLeave={() => this.setHover(false)}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
<Tooltip
id="copy-to-clipboard-tooltip"
Expand All @@ -220,23 +211,22 @@ class TableElement extends React.PureComponent {
) : (
<Fade
data-test="fade"
hovered={this.state.hovered}
hovered={hovered}
onClick={e => e.stopPropagation()}
>
{this.renderControls()}
{renderControls()}
</Fade>
)}
</div>
</div>
);
}
};

renderBody() {
const { table } = this.props;
const renderBody = () => {
let cols;
if (table.columns) {
cols = table.columns.slice();
if (this.state.sortColumns) {
if (sortColumns) {
cols.sort((a, b) => {
const colA = a.name.toUpperCase();
const colB = b.name.toUpperCase();
Expand All @@ -253,33 +243,31 @@ class TableElement extends React.PureComponent {

const metadata = (
<div
onMouseEnter={() => this.setHover(true)}
onMouseLeave={() => this.setHover(false)}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
css={{ paddingTop: 6 }}
>
{this.renderWell()}
{renderWell()}
<div>
{cols &&
cols.map(col => <ColumnElement column={col} key={col.name} />)}
corbinrobb marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>
);
return metadata;
}
};

render() {
return (
<Collapse.Panel
{...this.props}
header={this.renderHeader()}
className="TableElement"
forceRender="true"
>
{this.renderBody()}
</Collapse.Panel>
);
}
}
return (
<Collapse.Panel
{...props}
header={renderHeader()}
className="TableElement"
forceRender="true"
>
{renderBody()}
</Collapse.Panel>
);
};

TableElement.propTypes = propTypes;
TableElement.defaultProps = defaultProps;
Expand Down