Skip to content

Commit

Permalink
Allow sorting by computed columns in EuiInMemoryTable (#2044)
Browse files Browse the repository at this point in the history
* Allow EuiInMemoryTable to sort computed columns

* New unit tests for computed table column sorting

* Updated props docs for tables' sortable prop

* changelog

* Update src-docs/src/views/tables/in_memory/in_memory_custom_sorting.js

Co-Authored-By: Rory Hunter <[email protected]>

* PR feedback

* make CI happy

* Fix bug in reporting table sort status to parent

* Fix column sort bug
  • Loading branch information
chandlerprall authored Jun 18, 2019
1 parent 5b059ee commit 621fd55
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 134 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
## [`master`](https://github.com/elastic/eui/tree/master)

- Changed `EuiNavDrawerFlyout` title from `h5` to `div` ([#2040](https://github.com/elastic/eui/pull/2040))

**Bug fixes**

- Fixed proptype for `EuiCopy`'s `children` ([#2048](https://github.com/elastic/eui/pull/2048))
- Fixed `EuiInMemoryTable` to allow sorting on computed columns ([#2044](https://github.com/elastic/eui/pull/2044))
- Fixed `EuiInMemoryTable` to allow sorting on computed columns ([#2044](https://github.com/elastic/eui/pull/2044))

## [`12.0.0`](https://github.com/elastic/eui/tree/v12.0.0)

Expand Down
11 changes: 9 additions & 2 deletions src-docs/src/views/tables/basic/props_info.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,11 @@ export const propsInfo = {
type: { name: 'string (e.g. "30%", "100px", etc..)' },
},
sortable: {
description: 'Defines whether the user can sort on this column',
description:
'Defines whether the user can sort on this column. If a function is provided, this function returns the value to sort against.',
required: false,
defaultValue: { value: 'false' },
type: { name: 'boolean' },
type: { name: '"boolean" | "function"' },
},
align: {
description: 'Defines the horizontal alignment of the column',
Expand Down Expand Up @@ -303,6 +304,12 @@ export const propsInfo = {
required: false,
type: { name: 'string (e.g. "30%", "100px", etc..)' },
},
sortable: {
description:
'If provided, allows this column to be sorted on. Must return the value to sort against.',
required: false,
type: { name: 'function' },
},
truncateText: {
description:
"Indicates whether this column should truncate its content when it doesn't fit",
Expand Down
21 changes: 13 additions & 8 deletions src-docs/src/views/tables/in_memory/in_memory_custom_sorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import React from 'react';
import { EuiInMemoryTable } from '../../../../../src/components';

const data = [
{ animal: 'snail', weight: 25, humanFriendlyWeight: '25g' },
{ animal: 'peregrine falcon', weight: 900, humanFriendlyWeight: '0.9kg' },
{ animal: 'small dog', weight: 4500, humanFriendlyWeight: '4.5kg' },
{ animal: 'brown bear', weight: 180000, humanFriendlyWeight: '180kg' },
{ animal: 'elephant', weight: 5440000, humanFriendlyWeight: '5440kg' },
{ animal: 'giraffe', weight: 1180000, humanFriendlyWeight: '1180kg' },
{ animal: 'snail', weight: 25 },
{ animal: 'peregrine falcon', weight: 900 },
{ animal: 'small dog', weight: 4500 },
{ animal: 'brown bear', weight: 180000 },
{ animal: 'elephant', weight: 5440000 },
{ animal: 'giraffe', weight: 1180000 },
];

export const Table = () => {
Expand All @@ -18,15 +18,20 @@ export const Table = () => {
sortable: true,
},
{
field: 'humanFriendlyWeight',
name: 'Weight',
render: ({ weight }) => `${weight / 1000}kg`,
sortable: ({ weight }) => weight,
},
{
field: 'weight',
name: 'Weight (grams)',
sortable: true,
},
];

const sorting = {
sort: {
field: 'humanFriendlyWeight',
field: 'Weight',
direction: 'asc',
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ exports[`EuiInMemoryTable behavior pagination 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -652,7 +651,6 @@ exports[`EuiInMemoryTable empty array 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand All @@ -674,7 +672,6 @@ exports[`EuiInMemoryTable with executeQueryOptions 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -725,7 +722,7 @@ exports[`EuiInMemoryTable with initial sorting 1`] = `
"allowNeutralSort": true,
"sort": Object {
"direction": "desc",
"field": "name",
"field": "Name",
},
}
}
Expand All @@ -742,7 +739,6 @@ exports[`EuiInMemoryTable with items 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -779,7 +775,6 @@ exports[`EuiInMemoryTable with items and expanded item 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -824,7 +819,6 @@ exports[`EuiInMemoryTable with items and message - expecting to show the items 1
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -861,7 +855,6 @@ exports[`EuiInMemoryTable with message 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand All @@ -883,7 +876,6 @@ exports[`EuiInMemoryTable with message and loading 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand All @@ -906,7 +898,6 @@ exports[`EuiInMemoryTable with pagination 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -952,7 +943,6 @@ exports[`EuiInMemoryTable with pagination and default page size and index 1`] =
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -994,7 +984,6 @@ exports[`EuiInMemoryTable with pagination and selection 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -1050,7 +1039,6 @@ exports[`EuiInMemoryTable with pagination, default page size and error 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -1093,7 +1081,6 @@ exports[`EuiInMemoryTable with pagination, hiding the per page options 1`] = `
"description": "description",
"field": "name",
"name": "Name",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -1224,7 +1211,6 @@ exports[`EuiInMemoryTable with pagination, selection, sorting and simple search
},
],
"name": "Actions",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -1299,7 +1285,6 @@ exports[`EuiInMemoryTable with pagination, selection, sorting and a single recor
},
],
"name": "Actions",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -1459,7 +1444,6 @@ exports[`EuiInMemoryTable with pagination, selection, sorting and configured sea
},
],
"name": "Actions",
"sortable": false,
},
]
}
Expand Down Expand Up @@ -1503,46 +1487,3 @@ exports[`EuiInMemoryTable with pagination, selection, sorting and configured sea
/>
</div>
`;

exports[`EuiInMemoryTable with sorting 1`] = `
<EuiBasicTable
aria-label="aria-label"
className="testClass1 testClass2"
columns={
Array [
Object {
"description": "description",
"field": "name",
"name": "Name",
"sortable": true,
},
]
}
data-test-subj="test subject string"
items={
Array [
Object {
"id": "1",
"name": "name1",
},
Object {
"id": "2",
"name": "name2",
},
Object {
"id": "3",
"name": "name3",
},
]
}
noItemsMessage="No items found"
onChange={[Function]}
responsive={true}
sorting={
Object {
"allowNeutralSort": true,
"sort": undefined,
}
}
/>
`;
30 changes: 24 additions & 6 deletions src/components/basic_table/basic_table.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export const FieldDataColumnTypeShape = {
description: PropTypes.string,
dataType: PropTypes.oneOf(DATA_TYPES),
width: PropTypes.string,
sortable: PropTypes.bool,
sortable: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
align: PropTypes.oneOf([LEFT_ALIGNMENT, RIGHT_ALIGNMENT]),
truncateText: PropTypes.bool,
render: PropTypes.func, // ((value, record) => PropTypes.node (also see [services/value_renderer] for basic implementations)
Expand All @@ -128,6 +128,7 @@ export const ComputedColumnType = PropTypes.shape({
render: PropTypes.func.isRequired, // (record) => PropTypes.node
name: PropTypes.node,
description: PropTypes.string,
sortable: PropTypes.func,
width: PropTypes.string,
truncateText: PropTypes.bool,
});
Expand Down Expand Up @@ -326,7 +327,8 @@ export class EuiBasicTable extends Component {
if (
currentCriteria &&
currentCriteria.sort &&
currentCriteria.sort.field === column.field
(currentCriteria.sort.field === column.field ||
currentCriteria.sort.field === column.name)
) {
direction = SortDirection.reverse(currentCriteria.sort.direction);
}
Expand All @@ -340,7 +342,7 @@ export class EuiBasicTable extends Component {
size: currentCriteria.page.size,
},
sort: {
field: column.field,
field: column.field || column.name,
direction,
},
};
Expand Down Expand Up @@ -563,12 +565,25 @@ export class EuiBasicTable extends Component {

// computed column
if (!field) {
const sorting = {};
// computed columns are only sortable if their `sortable` is a function
if (this.props.sorting && typeof sortable === 'function') {
const sortDirection = this.resolveColumnSortDirection(column);
sorting.isSorted = !!sortDirection;
sorting.isSortAscending = sortDirection
? SortDirection.isAsc(sortDirection)
: undefined;
sorting.onSort = this.resolveColumnOnSort(column);
sorting.allowNeutralSort = this.props.sorting.allowNeutralSort;
}
headers.push(
<EuiTableHeaderCell
key={`_computed_column_h_${index}`}
align={columnAlign}
width={width}
mobileOptions={mobileOptions}>
mobileOptions={mobileOptions}
data-test-subj={`tableHeaderCell_${name}_${index}`}
{...sorting}>
{name}
</EuiTableHeaderCell>
);
Expand Down Expand Up @@ -982,7 +997,10 @@ export class EuiBasicTable extends Component {
if (!sorting || !sorting.sort || !column.sortable) {
return;
}
if (sorting.sort.field === column.field) {
if (
sorting.sort.field === column.field ||
sorting.sort.field === column.name
) {
return sorting.sort.direction;
}
};
Expand All @@ -994,7 +1012,7 @@ export class EuiBasicTable extends Component {
}
if (!this.props.onChange) {
throw new Error(`BasicTable is configured to be sortable on column [${
column.field
column.name
}] but
[onChange] is not configured. This callback must be implemented to handle the sort requests`);
}
Expand Down
Loading

0 comments on commit 621fd55

Please sign in to comment.