Table Component: Update showcols to use keys (https://github.com/woocommerce/woocommerce-admin/pull/971)
* component/table: Update showcols to use keys This updates the table component to use keys to keep track of which columns should be visible instead of column indices. This will be necessary for keeping track of which columns were selected after a component has been unmounted and re-mounted again later. (e.g. for persistence or saving of user preferences) * components/table: Add changelog entry
This commit is contained in:
parent
96d930b119
commit
8bb3175172
|
@ -1,3 +1,7 @@
|
|||
# 1.3.0
|
||||
|
||||
- Update `<Table />` to use header keys to denote which columns are shown
|
||||
|
||||
# 1.2.0
|
||||
|
||||
- Update `Search` to exclude already-selected items
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { find, findIndex, first, isEqual, noop, partial, uniq } from 'lodash';
|
||||
import { find, first, includes, isEqual, noop, partial, uniq, without } from 'lodash';
|
||||
import { IconButton, ToggleControl } from '@wordpress/components';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
|
@ -46,11 +46,12 @@ class TableCard extends Component {
|
|||
constructor( props ) {
|
||||
super( props );
|
||||
const { compareBy, query } = props;
|
||||
this.state = {
|
||||
selectedRows: getIdsFromQuery( query[ compareBy ] ),
|
||||
showCols: props.headers.map( ( { hiddenByDefault } ) => ! hiddenByDefault ),
|
||||
};
|
||||
this.toggleCols = this.toggleCols.bind( this );
|
||||
|
||||
const showCols = props.headers.map( ( { key, hiddenByDefault } ) => ! hiddenByDefault && key ).filter( Boolean );
|
||||
const selectedRows = getIdsFromQuery( query[ compareBy ] );
|
||||
|
||||
this.state = { showCols, selectedRows };
|
||||
this.onColumnToggle = this.onColumnToggle.bind( this );
|
||||
this.onClickDownload = this.onClickDownload.bind( this );
|
||||
this.onCompare = this.onCompare.bind( this );
|
||||
this.onSearch = this.onSearch.bind( this );
|
||||
|
@ -78,37 +79,55 @@ class TableCard extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
toggleCols( selected ) {
|
||||
const { headers, query, onQueryChange } = this.props;
|
||||
return () => {
|
||||
// Handle hiding a sorted column
|
||||
if ( query.orderby ) {
|
||||
const sortBy = findIndex( headers, { key: query.orderby } );
|
||||
if ( sortBy === selected ) {
|
||||
const defaultSort = find( headers, { defaultSort: true } ) || first( headers ) || {};
|
||||
onQueryChange( 'sort' )( defaultSort.key, 'desc' );
|
||||
}
|
||||
}
|
||||
getVisibleHeaders() {
|
||||
const { headers } = this.props;
|
||||
const { showCols } = this.state;
|
||||
return headers.filter( ( { key } ) => includes( showCols, key ) );
|
||||
}
|
||||
|
||||
this.setState( prevState => ( {
|
||||
showCols: prevState.showCols.map(
|
||||
( toggled, i ) => ( selected === i ? ! toggled : toggled )
|
||||
),
|
||||
} ) );
|
||||
getVisibleRows() {
|
||||
const { headers, rows } = this.props;
|
||||
const { showCols } = this.state;
|
||||
|
||||
return rows.map( row => {
|
||||
return headers.map( ( { key }, i ) => {
|
||||
return includes( showCols, key ) && row[ i ];
|
||||
} ).filter( Boolean );
|
||||
} );
|
||||
}
|
||||
|
||||
onColumnToggle( key ) {
|
||||
const { headers, query, onQueryChange } = this.props;
|
||||
|
||||
return ( visible ) => {
|
||||
this.setState( prevState => {
|
||||
const hasKey = includes( prevState.showCols, key );
|
||||
|
||||
if ( visible && ! hasKey ) {
|
||||
return { showCols: [ ...prevState.showCols, key ] };
|
||||
}
|
||||
if ( ! visible && hasKey ) {
|
||||
// Handle hiding a sorted column
|
||||
if ( query.orderby === key ) {
|
||||
const defaultSort = find( headers, { defaultSort: true } ) || first( headers ) || {};
|
||||
onQueryChange( 'sort' )( defaultSort.key, 'desc' );
|
||||
}
|
||||
|
||||
return { showCols: without( prevState.showCols, key ) };
|
||||
}
|
||||
return {};
|
||||
} );
|
||||
};
|
||||
}
|
||||
|
||||
onClickDownload() {
|
||||
const { headers, query, onClickDownload, rows, title } = this.props;
|
||||
const { showCols } = this.state;
|
||||
const visibleHeaders = headers.filter( ( header, i ) => showCols[ i ] );
|
||||
const visibleRows = rows.map( row => row.filter( ( cell, i ) => showCols[ i ] ) );
|
||||
const { query, onClickDownload, title } = this.props;
|
||||
|
||||
// @TODO The current implementation only downloads the contents displayed in the table.
|
||||
// Another solution is required when the data set is larger (see #311).
|
||||
downloadCSVFile(
|
||||
generateCSVFileName( title, query ),
|
||||
generateCSVDataFromTable( visibleHeaders, visibleRows )
|
||||
generateCSVDataFromTable( this.getVisibleHeaders(), this.getVisibleRows() )
|
||||
);
|
||||
|
||||
if ( onClickDownload ) {
|
||||
|
@ -137,16 +156,6 @@ class TableCard extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
filterCols( rows = [] ) {
|
||||
const { showCols } = this.state;
|
||||
// Header is a 1d array
|
||||
if ( ! Array.isArray( first( rows ) ) ) {
|
||||
return rows.filter( ( col, i ) => showCols[ i ] );
|
||||
}
|
||||
// Rows is a 2d array
|
||||
return rows.map( row => row.filter( ( col, i ) => showCols[ i ] ) );
|
||||
}
|
||||
|
||||
selectAllRows( event ) {
|
||||
const { ids } = this.props;
|
||||
if ( event.target.checked ) {
|
||||
|
@ -223,8 +232,8 @@ class TableCard extends Component {
|
|||
} = this.props;
|
||||
const { selectedRows, showCols } = this.state;
|
||||
const allHeaders = this.props.headers;
|
||||
let headers = this.filterCols( this.props.headers );
|
||||
let rows = this.filterCols( this.props.rows );
|
||||
let headers = this.getVisibleHeaders();
|
||||
let rows = this.getVisibleRows();
|
||||
if ( compareBy ) {
|
||||
rows = rows.map( ( row, i ) => {
|
||||
return [ this.getCheckbox( i ), ...row ];
|
||||
|
@ -281,16 +290,16 @@ class TableCard extends Component {
|
|||
menu={
|
||||
<EllipsisMenu label={ __( 'Choose which values to display', 'wc-admin' ) }>
|
||||
<MenuTitle>{ __( 'Columns:', 'wc-admin' ) }</MenuTitle>
|
||||
{ allHeaders.map( ( { label, required }, i ) => {
|
||||
{ allHeaders.map( ( { key, label, required } ) => {
|
||||
if ( required ) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<MenuItem key={ i } onInvoke={ this.toggleCols( i ) }>
|
||||
<MenuItem key={ key } onInvoke={ this.onColumnToggle( key ) }>
|
||||
<ToggleControl
|
||||
label={ label }
|
||||
checked={ !! showCols[ i ] }
|
||||
onChange={ this.toggleCols( i ) }
|
||||
checked={ includes( showCols, key ) }
|
||||
onChange={ this.onColumnToggle( key ) }
|
||||
/>
|
||||
</MenuItem>
|
||||
);
|
||||
|
|
|
@ -75,7 +75,7 @@ describe( 'TableCard', () => {
|
|||
/>
|
||||
);
|
||||
tableCard.setState( {
|
||||
showCols: [ true, true, true, true, false, true, true, true ],
|
||||
showCols: [ 'date', 'orders_count', 'gross_revenue', 'refunds', 'taxes', 'shipping', 'net_revenue' ],
|
||||
} );
|
||||
|
||||
const downloadButton = tableCard.findWhere(
|
||||
|
|
Loading…
Reference in New Issue