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

[EuiDataGrid] use schema information when sorting #2419

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b9839fe
cell expansion working mostly
snide Sep 23, 2019
3cfae45
fix double import
snide Sep 23, 2019
4209301
add search to field selector
snide Sep 23, 2019
eb3a495
euitext
snide Sep 23, 2019
ab2a03b
Merge branch 'feature/euidatagrid' into grid/expand
snide Sep 25, 2019
2c35acb
cell epansion is now optional through a config
snide Sep 25, 2019
fc5d03e
keydown event for cells
snide Sep 25, 2019
29f8a66
Merge branch 'feature/euidatagrid' into grid/expand
snide Sep 29, 2019
5302ce5
remove tabbables
snide Sep 30, 2019
e4d9910
Clean up some code & tests
chandlerprall Oct 2, 2019
ceaa11e
Remove unused line of code
chandlerprall Oct 2, 2019
346811a
Center popover against cell
chandlerprall Oct 3, 2019
cb76824
Update euidatagridcell popover placement, trigger, dom structure, and…
chandlerprall Oct 3, 2019
d35e459
Restore focus to grid cell when popover was in response to mouse click
chandlerprall Oct 3, 2019
f3edb5e
Allow grid column selection to be searchable
chandlerprall Oct 4, 2019
59afd89
Refactor expansion popover formatting, allow custom ones
chandlerprall Oct 4, 2019
78332de
schema-based sort comparators
chandlerprall Oct 7, 2019
57930fa
Merge branch 'feature/euidatagrid' into feature/euidatagrid-schema-sort
chandlerprall Oct 11, 2019
b709d8c
reverse boolean sort to be true-false
snide Oct 11, 2019
084c31b
adds json schema sorting, fixes issue with popover
snide Oct 11, 2019
64266e7
Weaken the currency type detector when values have a period in their …
chandlerprall Oct 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions src-docs/src/views/datagrid/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,9 @@ const columns = [
const data = [];

for (let i = 1; i < 5; i++) {
data.push({
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
email: <EuiLink href="">{fake('{{internet.email}}')}</EuiLink>,
location: (
<Fragment>
{`${fake('{{address.city}}')}, `}
<EuiLink href="https://google.com">
{fake('{{address.country}}')}
</EuiLink>
</Fragment>
),
date: fake('{{date.past}}'),
account: fake('{{finance.account}}'),
amount: fake('${{finance.amount}}'),
json: JSON.stringify([
let json;
if (i < 3) {
json = JSON.stringify([
{
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
email: fake('{{internet.email}}'),
Expand All @@ -76,7 +64,30 @@ for (let i = 1; i < 5; i++) {
},
],
},
]),
]);
} else {
json = JSON.stringify([
{
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
},
]);
}

data.push({
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
email: <EuiLink href="">{fake('{{internet.email}}')}</EuiLink>,
location: (
<Fragment>
{`${fake('{{address.city}}')}, `}
<EuiLink href="https://google.com">
{fake('{{address.country}}')}
</EuiLink>
</Fragment>
),
date: fake('{{date.past}}'),
account: fake('{{finance.account}}'),
amount: fake('${{finance.amount}}'),
json: json,
version: fake('{{system.semver}}'),
});
}
Expand Down
192 changes: 99 additions & 93 deletions src/components/datagrid/column_sorting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,104 +149,110 @@ export const useColumnSorting = (
</p>
</EuiText>
)}
<EuiPopoverFooter>
<EuiFlexGroup
gutterSize="m"
justifyContent="spaceBetween"
responsive={false}>
<EuiFlexItem grow={false}>
<EuiPopover
data-test-subj="dataGridColumnSortingPopoverColumnSelection"
isOpen={avilableColumnsisOpen}
closePopover={() => setAvailableColumnsIsOpen(false)}
anchorPosition="downLeft"
ownFocus
panelPaddingSize="s"
button={
{(inactiveColumns.length > 0 || sorting.columns.length > 0) && (
<EuiPopoverFooter>
<EuiFlexGroup
gutterSize="m"
justifyContent="spaceBetween"
responsive={false}>
<EuiFlexItem grow={false}>
{inactiveColumns.length > 0 && (
<EuiPopover
data-test-subj="dataGridColumnSortingPopoverColumnSelection"
isOpen={avilableColumnsisOpen}
closePopover={() => setAvailableColumnsIsOpen(false)}
anchorPosition="downLeft"
ownFocus
panelPaddingSize="s"
button={
<EuiButtonEmpty
size="xs"
flush="left"
iconType="arrowDown"
iconSide="right"
onClick={() =>
setAvailableColumnsIsOpen(!avilableColumnsisOpen)
}>
<EuiI18n
token="euiColumnSorting.pickFields"
default="Pick fields to sort by"
/>
</EuiButtonEmpty>
}>
<EuiI18n
token="euiColumnSorting.sortFieldAriaLabel"
default="Sort by: ">
{(sortFieldAriaLabel: string) => (
<div
className="euiDataGridColumnSorting__fieldList"
role="listbox">
{inactiveColumns.map(({ id }) => (
<button
key={id}
className="euiDataGridColumnSorting__field"
aria-label={`${sortFieldAriaLabel} ${id}`}
role="option"
aria-selected="false"
data-test-subj={`dataGridColumnSortingPopoverColumnSelection-${id}`}
onClick={() => {
const nextColumns = [...sorting.columns];
nextColumns.push({ id, direction: 'asc' });
sorting.onSort(nextColumns);
}}>
<EuiFlexGroup
alignItems="center"
gutterSize="s"
component="span">
<EuiFlexItem grow={false}>
<EuiIcon
color={
schema.hasOwnProperty(id) &&
schema[id].columnType != null
? getDetailsForSchema(
schema[id].columnType
).color
: defaultSchemaColor
}
type={
schema.hasOwnProperty(id) &&
schema[id].columnType != null
? getDetailsForSchema(
schema[id].columnType
).icon
: 'string'
}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs">
<span>{id}</span>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</button>
))}
</div>
)}
</EuiI18n>
</EuiPopover>
)}
</EuiFlexItem>
{sorting.columns.length > 0 ? (
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="xs"
flush="left"
iconType="arrowDown"
iconSide="right"
onClick={() =>
setAvailableColumnsIsOpen(!avilableColumnsisOpen)
}>
flush="right"
onClick={() => sorting.onSort([])}>
<EuiI18n
token="euiColumnSorting.pickFields"
default="Pick fields to sort by"
token="euiColumnSorting.clearAll"
default="Clear sorting"
/>
</EuiButtonEmpty>
}>
<EuiI18n
token="euiColumnSorting.sortFieldAriaLabel"
default="Sort by: ">
{(sortFieldAriaLabel: string) => (
<div
className="euiDataGridColumnSorting__fieldList"
role="listbox">
{inactiveColumns.map(({ id }) => (
<button
key={id}
className="euiDataGridColumnSorting__field"
aria-label={`${sortFieldAriaLabel} ${id}`}
role="option"
aria-selected="false"
data-test-subj={`dataGridColumnSortingPopoverColumnSelection-${id}`}
onClick={() => {
const nextColumns = [...sorting.columns];
nextColumns.push({ id, direction: 'asc' });
sorting.onSort(nextColumns);
}}>
<EuiFlexGroup
alignItems="center"
gutterSize="s"
component="span">
<EuiFlexItem grow={false}>
<EuiIcon
color={
schema.hasOwnProperty(id) &&
schema[id].columnType != null
? getDetailsForSchema(schema[id].columnType)
.color
: defaultSchemaColor
}
type={
schema.hasOwnProperty(id) &&
schema[id].columnType != null
? getDetailsForSchema(schema[id].columnType)
.icon
: 'string'
}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText size="xs">
<span>{id}</span>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</button>
))}
</div>
)}
</EuiI18n>
</EuiPopover>
</EuiFlexItem>
{sorting.columns.length > 0 ? (
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="xs"
flush="right"
onClick={() => sorting.onSort([])}>
<EuiI18n
token="euiColumnSorting.clearAll"
default="Clear sorting"
/>
</EuiButtonEmpty>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
</EuiPopoverFooter>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
</EuiPopoverFooter>
)}
</EuiPopover>
);

Expand Down
57 changes: 44 additions & 13 deletions src/components/datagrid/data_grid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,24 @@ function getColumnSortDirection(
columnSelectionPopover = datagrid.find(
'EuiPopover[data-test-subj="dataGridColumnSortingPopoverColumnSelection"]'
);
expect(columnSelectionPopover).euiPopoverToBeOpen();
// popover will go away if all of the columns are selected
if (columnSelectionPopover.length > 0) {
expect(columnSelectionPopover).euiPopoverToBeOpen();

popoverButton = columnSelectionPopover
.find('div[className="euiPopover__anchor"]')
.find('[onClick]')
.first();
// @ts-ignore-next-line
act(() => popoverButton.props().onClick());

popoverButton = columnSelectionPopover
.find('div[className="euiPopover__anchor"]')
.find('[onClick]')
.first();
// @ts-ignore-next-line
act(() => popoverButton.props().onClick());
datagrid.update();

datagrid.update();

columnSelectionPopover = datagrid.find(
'EuiPopover[data-test-subj="dataGridColumnSortingPopoverColumnSelection"]'
);
expect(columnSelectionPopover).not.euiPopoverToBeOpen();
columnSelectionPopover = datagrid.find(
'EuiPopover[data-test-subj="dataGridColumnSortingPopoverColumnSelection"]'
);
expect(columnSelectionPopover).not.euiPopoverToBeOpen();
}

// find the column sorter
columnSelectionPopover = datagrid.find(
Expand Down Expand Up @@ -1234,6 +1237,34 @@ Array [
]);
});
});

it('uses schema information to sort', () => {
const component = mount(
<EuiDataGrid
aria-label="test"
columns={[{ id: 'A' }, { id: 'B' }]}
rowCount={5}
renderCellValue={({ rowIndex, columnId }) =>
// render A 0->4 and B 12->8
columnId === 'A' ? rowIndex : 12 - rowIndex
}
inMemory={{ level: 'sorting' }}
sorting={{
columns: [{ id: 'B', direction: 'asc' }],
onSort: () => {},
}}
/>
);

expect(extractGridData(component)).toEqual([
['A', 'B'],
['4', '8'],
['3', '9'],
['2', '10'],
['1', '11'],
['0', '12'],
]);
});
});

describe('keyboard controls', () => {
Expand Down
9 changes: 8 additions & 1 deletion src/components/datagrid/data_grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, {
useEffect,
Fragment,
ReactChild,
useMemo,
} from 'react';
import classNames from 'classnames';
import { EuiI18n } from '../i18n';
Expand Down Expand Up @@ -44,6 +45,7 @@ import {
getMergedSchema,
SchemaDetector,
useDetectSchema,
schemaDetectors as providedSchemaDetectors,
} from './data_grid_schema';
import { useColumnSorting } from './column_sorting';

Expand Down Expand Up @@ -317,9 +319,13 @@ export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = props => {

const [inMemoryValues, onCellRender] = useInMemoryValues(inMemory, rowCount);

const allSchemaDetetors = useMemo(
() => [...providedSchemaDetectors, ...(schemaDetectors || [])],
[schemaDetectors]
);
const detectedSchema = useDetectSchema(
inMemoryValues,
schemaDetectors,
allSchemaDetetors,
inMemory != null
);
const mergedSchema = getMergedSchema(detectedSchema, columns);
Expand Down Expand Up @@ -465,6 +471,7 @@ export const EuiDataGrid: FunctionComponent<EuiDataGridProps> = props => {
inMemory={inMemory}
columns={visibleColumns}
schema={mergedSchema}
schemaDetectors={allSchemaDetetors}
expansionFormatters={expansionFormatters}
focusedCell={focusedCell}
onCellFocus={setFocusedCell}
Expand Down
Loading