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] Add footer row #3770

Merged
merged 21 commits into from
Sep 17, 2020
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
7750ee1
Add footer_row into data_grid
sulemanof Jul 14, 2020
6c4d335
Add documentation description
sulemanof Jul 21, 2020
b04c5a7
Update snapshots
sulemanof Jul 21, 2020
649a05f
Merge remote-tracking branch 'upstream/master' into data_grid/footer_row
sulemanof Jul 21, 2020
34d8b1c
Merge branch 'master' into data_grid/footer_row
chandlerprall Jul 29, 2020
521a222
Revert changes in control_columns example
sulemanof Jul 30, 2020
4bb6ad3
Get rid of footerCellRender prop in a column
sulemanof Jul 30, 2020
326516e
Merge remote-tracking branch 'upstream/master' into data_grid/footer_row
sulemanof Aug 19, 2020
2e5d9f8
Fix review comments
sulemanof Aug 20, 2020
8b40a3f
Update styling example
sulemanof Aug 20, 2020
4564183
Merge remote-tracking branch 'upstream/master' into data_grid/footer_row
sulemanof Aug 24, 2020
652a6fe
Make footer cell expandable
sulemanof Aug 24, 2020
e12a613
Move callback outside of the component
sulemanof Aug 24, 2020
918b883
make footer row sticky and adjust styles
andreadelrio Sep 1, 2020
8fa9965
added bg to shaded footer and remove unneeded line from example
andreadelrio Sep 15, 2020
36b909f
add cl
andreadelrio Sep 15, 2020
52e4550
made sticky footer optional
andreadelrio Sep 16, 2020
5b52f23
Merge pull request #1 from andreadelrio/footer_row_styles
sulemanof Sep 16, 2020
7f662f4
Merge remote-tracking branch 'upstream/master' into data_grid/footer_row
sulemanof Sep 16, 2020
9b65ef6
Return back webpack devtool
sulemanof Sep 16, 2020
030f286
small clean up in footer row example & changelog entry
chandlerprall Sep 16, 2020
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## [`master`](https://github.com/elastic/eui/tree/master)

No public interface changes since `29.0.0`.
- Added footer row to `EuiDataGrid` via the `renderFooterCellValue` prop ([#3770](https://github.com/elastic/eui/pull/3770))

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

Expand Down
2 changes: 2 additions & 0 deletions src-docs/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import { DataGridSchemaExample } from './views/datagrid/datagrid_schema_example'
import { DataGridFocusExample } from './views/datagrid/datagrid_focus_example';
import { DataGridStylingExample } from './views/datagrid/datagrid_styling_example';
import { DataGridControlColumnsExample } from './views/datagrid/datagrid_controlcolumns_example';
import { DataGridFooterRowExample } from './views/datagrid/datagrid_footer_row_example';

import { DatePickerExample } from './views/date_picker/date_picker_example';

Expand Down Expand Up @@ -371,6 +372,7 @@ const navigation = [
DataGridFocusExample,
DataGridStylingExample,
DataGridControlColumnsExample,
DataGridFooterRowExample,
TableExample,
TableInMemoryExample,
].map(example => createExample(example)),
Expand Down
71 changes: 71 additions & 0 deletions src-docs/src/views/datagrid/datagrid_footer_row_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { Fragment } from 'react';

import { renderToHtml } from '../../services';

import { GuideSectionTypes } from '../../components';
import { EuiDataGrid, EuiCodeBlock, EuiCode } from '../../../../src/components';

import DataGridFooterRow from './footer_row';
const dataGridControlColumnsSource = require('!!raw-loader!./footer_row');
const dataGridControlColumnsHtml = renderToHtml(DataGridFooterRow);

import { EuiDataGridControlColumn } from '!!prop-loader!../../../../src/components/datagrid/data_grid_types';
import { EuiDataGridCellValueElementProps } from '!!prop-loader!../../../../src/components/datagrid/data_grid_cell';

const gridSnippet = `const footerCellValues = {
// desired data
};

<EuiDataGrid
{...usualProps}
renderFooterCellValue={({ columnId }) =>
footerCellValues[columnId] || null
}
/>
`;

export const DataGridFooterRowExample = {
title: 'Data grid footer row',
sections: [
{
source: [
{
type: GuideSectionTypes.JS,
code: dataGridControlColumnsSource,
},
{
type: GuideSectionTypes.HTML,
code: dataGridControlColumnsHtml,
},
],
text: (
<Fragment>
<p>
A footer row can be used to include value aggregations to the grid.
Values could be based on the dataset, such as sum/average/min/max of
numeric values in a column, or any other necessary data.
</p>
<p>
The footer row is defined by passing{' '}
<EuiCode>renderFooterCellValue</EuiCode> function prop into
EuiDataGrid. <EuiCode>renderFooterCellValue</EuiCode> acts like a
React component, receiving{' '}
<EuiCode>EuiDataGridCellValueElementProps</EuiCode> and returning a
React node.
</p>
<EuiCodeBlock language="javascript" paddingSize="s" isCopyable>
{gridSnippet}
</EuiCodeBlock>
</Fragment>
),
components: { DataGridFooterRow },

props: {
EuiDataGrid,
EuiDataGridControlColumn,
EuiDataGridCellValueElementProps,
},
demo: <DataGridFooterRow />,
},
],
};
1 change: 1 addition & 0 deletions src-docs/src/views/datagrid/datagrid_styling_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const gridSnippet = `<EuiDataGrid
// If showStyleSelector={true} from toolbarVisibility, these last two will be superceded by what the user decides.
fontSize: 'm',
cellPadding: 'm',
footer: 'overline'
}}
/>
`;
Expand Down
143 changes: 143 additions & 0 deletions src-docs/src/views/datagrid/footer_row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { fake } from 'faker';

import {
EuiDataGrid,
EuiSwitch,
EuiFlexGroup,
EuiFlexItem,
} from '../../../../src/components/';

const raw_data = [];

for (let i = 1; i < 20; i++) {
raw_data.push({
name: fake('{{name.lastName}}, {{name.firstName}} {{name.suffix}}'),
date: fake('{{date.past}}'),
amount: fake('${{commerce.price}}'),
phone: fake('{{phone.phoneNumber}}'),
version: fake('{{system.semver}}'),
});
}

const columns = [
{
id: 'name',
displayAsText: 'Name',
defaultSortDirection: 'asc',
},
{
id: 'date',
defaultSortDirection: 'desc',
},
{
id: 'amount',
},
{
id: 'phone',
isSortable: false,
},
{
id: 'version',
defaultSortDirection: 'desc',
},
];

const footerCellValues = {
amount: `Total: $${raw_data.reduce(
(acc, { amount }) => acc + Number(amount.split('$')[1]),
0
)}`,
version: `Latest: ${
raw_data.map(({ version }) => version).sort()[raw_data.length - 1]
}`,
};

export default () => {
// ** Pagination config
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
const onChangeItemsPerPage = useCallback(
pageSize =>
setPagination(pagination => ({ ...pagination, pageSize, pageIndex: 0 })),
[setPagination]
);
const onChangePage = useCallback(
pageIndex => setPagination(pagination => ({ ...pagination, pageIndex })),
[setPagination]
);

// Column visibility
const [visibleColumns, setVisibleColumns] = useState(() =>
columns.map(({ id }) => id)
); // initialize to the full set of columns

const renderCellValue = useMemo(() => {
return ({ rowIndex, columnId, setCellProps }) => {
useEffect(() => {
if (columnId === 'amount') {
if (raw_data.hasOwnProperty(rowIndex)) {
const numeric = parseFloat(
raw_data[rowIndex][columnId].match(/\d+\.\d+/)[0],
10
);
setCellProps({
style: {
backgroundColor: `rgba(0, 255, 0, ${numeric * 0.0002})`,
},
});
}
}
}, [rowIndex, columnId, setCellProps]);

return raw_data.hasOwnProperty(rowIndex)
? raw_data[rowIndex][columnId]
: null;
};
}, []);

const renderFooterCellValue = useCallback(
({ columnId }) => footerCellValues[columnId] || null,
[]
);

// Footer row
const [showFooterRow, setShowFooterRow] = useState(true);

return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiSwitch
label="Show footer row"
checked={showFooterRow}
onChange={e => setShowFooterRow(e.target.checked)}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiDataGrid
aria-label="Data grid footer row demo"
columns={columns}
columnVisibility={{ visibleColumns, setVisibleColumns }}
rowCount={raw_data.length}
renderCellValue={renderCellValue}
renderFooterCellValue={
chandlerprall marked this conversation as resolved.
Show resolved Hide resolved
showFooterRow ? renderFooterCellValue : undefined
}
pagination={{
...pagination,
pageSizeOptions: [10, 15, 20],
onChangeItemsPerPage: onChangeItemsPerPage,
onChangePage: onChangePage,
}}
onColumnResize={eventData => {
console.log(eventData);
}}
gridStyle={{
border: 'horizontal',
rowHover: 'highlight',
header: 'underline',
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
);
};
58 changes: 56 additions & 2 deletions src-docs/src/views/datagrid/styling.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
EuiAvatar,
EuiFlexGroup,
EuiFlexItem,
EuiCallOut,
} from '../../../../src/components/';

const columns = [
Expand All @@ -36,7 +37,7 @@ const columns = [

const data = [];

for (let i = 1; i < 5; i++) {
for (let i = 1; i < 6; i++) {
data.push({
avatar: (
<EuiAvatar
Expand All @@ -53,6 +54,13 @@ for (let i = 1; i < 5; i++) {
});
}

const footerCellValues = {
avatar: '5 accounts',
};

const renderFooterCellValue = ({ columnId }) =>
footerCellValues[columnId] || null;

export default class DataGrid extends Component {
constructor(props) {
super(props);
Expand Down Expand Up @@ -134,6 +142,21 @@ export default class DataGrid extends Component {
},
];

this.footerOptions = [
{
id: 'shade',
label: 'Shade',
},
{
id: 'overline',
label: 'Overline',
},
{
id: 'striped',
label: 'Striped',
},
];

this.showSortSelectorOptions = [
{
id: 'true',
Expand Down Expand Up @@ -231,6 +254,7 @@ export default class DataGrid extends Component {
isPopoverOpen: false,
isToolbarPopoverOpen: false,
headerSelected: 'underline',
footerSelected: 'overline',
showSortSelector: true,
showStyleSelector: true,
showColumnSelector: true,
Expand Down Expand Up @@ -285,6 +309,12 @@ export default class DataGrid extends Component {
});
};

onFooterChange = optionId => {
this.setState({
footerSelected: optionId,
});
};

onShowSortSelectorChange = optionId => {
this.setState({
showSortSelector: optionId === 'true',
Expand Down Expand Up @@ -429,7 +459,7 @@ export default class DataGrid extends Component {
isOpen={this.state.isPopoverOpen}
anchorPosition="rightUp"
closePopover={this.closePopover.bind(this)}>
<div style={{ width: 300 }}>
<div style={{ width: 380 }}>
<EuiFormRow label="Border" display="columnCompressed">
<EuiButtonGroup
isFullWidth
Expand Down Expand Up @@ -495,6 +525,17 @@ export default class DataGrid extends Component {
onChange={this.onHeaderChange}
/>
</EuiFormRow>

<EuiFormRow label="Footer" display="columnCompressed">
<EuiButtonGroup
isFullWidth
buttonSize="compressed"
legend="Footer"
options={this.footerOptions}
idSelected={this.state.footerSelected}
onChange={this.onFooterChange}
/>
</EuiFormRow>
</div>
</EuiPopover>
</EuiFlexItem>
Expand Down Expand Up @@ -619,6 +660,17 @@ export default class DataGrid extends Component {
</EuiFlexItem>
</EuiFlexGroup>

{this.state.footerSelected === 'striped' ? (
<>
<EuiSpacer />

<EuiCallOut
size="s"
title="A striped footer will be shaded depending on whether it is an even or an odd row considering the rest of the rows in the datagrid. Needs to be used with stripes={true}."
/>
</>
) : null}

<EuiSpacer />

<EuiDataGrid
Expand All @@ -636,9 +688,11 @@ export default class DataGrid extends Component {
stripes: this.state.stripesSelected,
rowHover: this.state.rowHoverSelected,
header: this.state.headerSelected,
footer: this.state.footerSelected,
}}
toolbarVisibility={toolbarConfig}
renderCellValue={({ rowIndex, columnId }) => data[rowIndex][columnId]}
renderFooterCellValue={renderFooterCellValue}
pagination={{
...pagination,
pageSizeOptions: [5, 10, 25],
Expand Down
Loading