Skip to content

Commit

Permalink
Summary rows (#1773)
Browse files Browse the repository at this point in the history
* feat: manually apply total rows implementation codes based on canary branch

* chores: minor tweak

* chores: fix idx

* chores: example small update

* chores: rename summaryRows; avoidhandling events or some unnecessary data for summary rows / cells

* fix: use correct interaction mask reference

* fix: merge issues

* feat: hide summary row checkbox

* chores: remove undeleted files due to merging

* chores: refactor some codes

* chores: refactor canvas

* chores: refactor Cell.tsx

* chores: remove unused CellContent

* fix: type reference

* fix: test in terms of types

* chores: catchup canary

* chores: add comment

* chores: minor changes

* chores: chrome, move summary rows out of canvas

* chores: minor styles tweak

* chores: remove deleted code

* chores: remove unnecessary width

* chores: css / scrolling logic tweak

* chores: tweak style

* fix: broken scrolling logic

* chores: remove dead code

* chores: remove cellContent

* Revert "chores: remove cellContent"

This reverts commit 7fdbfaf.

* chores: add cellContent back

* fix: broken behavior by merging

* chores: add SummaryRowRenderer

* chores: organize the code a little bit

* fix: type issue due to merge

* chores: sync scroll

* fix: type and summary row scrollLeft and height

* chores: revert scroll sync logic due to IE overflow-x:hidden / scrollLeft > 0 bug

* chores: move boundary style in if

* Clean up scrolling

* Fix canvas height calculation, nits
  • Loading branch information
qili26 authored and nstepien committed Oct 17, 2019
1 parent bc7daa2 commit 0f40988
Show file tree
Hide file tree
Showing 16 changed files with 395 additions and 85 deletions.
167 changes: 167 additions & 0 deletions examples/demos/example32-summary-rows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import React, { useCallback, useMemo, useState } from 'react';
import ReactDataGrid, { SelectColumn } from 'react-data-grid';
import Wrapper from './Wrapper';

function DecimalFormatter({ value, isSummaryRow, maximumFractionDigits }) {
const text = value.toLocaleString('en-US', maximumFractionDigits == null ? { maximumFractionDigits: 2 } : { maximumFractionDigits: 0 });
return isSummaryRow ? <strong>{text}</strong> : <div>{text}</div>;
}

function IntegerFormatter(props) {
return <DecimalFormatter {...props} maximumFractionDigits={0} />;
}

function TitleFormatter({ value, row: { selectedRowsCount }, isSummaryRow }) {
if (isSummaryRow) {
return <strong>{ selectedRowsCount >= 0 ? `${selectedRowsCount} row${selectedRowsCount > 1 ? 's' : ''} selected` : 'Total'}</strong>;
}

return <div>{value}</div>;
}

const columns = [
SelectColumn,
{
key: 'id',
name: 'ID',
frozen: true
},
{
key: 'task',
name: 'Title',
width: 200,
frozen: true,
formatter: TitleFormatter
},
{
key: 'priority',
name: 'Priority',
width: 200
},
{
key: 'issueType',
name: 'Issue Type',
width: 200
},
{
key: 'complete',
name: '% Complete',
width: 200
},
{
key: 'startDate',
name: 'Start Date',
width: 200
},
{
key: 'completeDate',
name: 'Expected Complete',
width: 200
},
{
key: 'cost',
name: 'Resource cost (USD)',
width: 200,
formatter: DecimalFormatter
},
{
key: 'hours',
name: '# of working hours',
width: 200,
formatter: IntegerFormatter
},
{
key: 'issueCount',
name: '# of issues',
width: 200,
formatter: IntegerFormatter
}
];

function getRandomDate(start, end) {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toLocaleDateString();
}

export default function Example() {
const [selectedRowIndexes, setSelectedRowIndexes] = useState(new Set([]));

const rows = useMemo(() => {
const rows = [];

for (let i = 1; i < 1000; i++) {
rows.push({
id: i,
task: `Task ${i}`,
complete: Math.min(100, Math.round(Math.random() * 110)),
priority: ['Critical', 'High', 'Medium', 'Low'][Math.floor(Math.random() * 4)],
issueType: ['Bug', 'Improvement', 'Epic', 'Story'][Math.floor(Math.random() * 4)],
startDate: getRandomDate(new Date(2015, 3, 1), new Date()),
completeDate: getRandomDate(new Date(), new Date(2016, 0, 1)),
cost: Math.random() * 25.2 + 1,
hours: Math.floor(Math.random() * 4 + 1),
issueCount: Math.floor(Math.random() * 8 + 1)
});
}

return rows;
}, []);

const summaryRows = useMemo(() => {
const selectedTotalRow = {
cost: 0,
hours: 0,
issueCount: 0,
selectedRowsCount: selectedRowIndexes.size
};

const totalRow = {
cost: 0,
hours: 0,
issueCount: 0,
selectedRowsCount: -1
};

rows.forEach((row, idx) => {
totalRow.cost += row.cost;
totalRow.hours += row.hours;
totalRow.issueCount += row.issueCount;

if (selectedRowIndexes.has(idx + 1)) {
selectedTotalRow.cost += row.cost;
selectedTotalRow.hours += row.hours;
selectedTotalRow.issueCount += row.issueCount;
}
});

return [selectedTotalRow, totalRow];
}, [rows, selectedRowIndexes]);

const rowGetter = useCallback((i) => rows[i], [rows]);

return (
<Wrapper title="Summary rows">
<ReactDataGrid
rowKey="id"
columns={columns}
rowGetter={rowGetter}
summaryRows={summaryRows}
rowsCount={rows.length}
minHeight={700}
selectedRows={selectedRowIndexes}
onSelectedRowsChange={setSelectedRowIndexes}
/>
<div
style={{
padding: '0 20px',
lineHeight: '35px',
textAlign: 'right',
background: '#eee',
border: '1px solid #ddd',
borderTop: 'none'
}}
>
<div>This is just a plain customized footer which renders next to the canvas. This area can potentially be used for pagination for example.</div>
</div>
</Wrapper>
);
}
1 change: 1 addition & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
.example {
overflow: auto;
flex-grow: 1;
margin: 0 8px;
}

h1 {
Expand Down
3 changes: 3 additions & 0 deletions examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import ScrollToRowIndex from './demos/example28-scroll-to-row-index';
import DescendingFirstSortable from './demos/example29-descendingFirstSortable';
import SelectionRangeEvents from './demos/example30-selection-range-events';
import IsScrolling from './demos/example31-isScrolling';
import SummaryRows from './demos/example32-summary-rows';

ReactDOM.render((
<StrictMode>
Expand Down Expand Up @@ -72,6 +73,7 @@ ReactDOM.render((
<li><NavLink to="/examples/descendingFirstSortable">Descending First Sortable Example</NavLink></li>
<li><NavLink to="/examples/selection-range-events">Selection Range Events Example</NavLink></li>
<li><NavLink to="/examples/isScrolling">IsScrolling Example</NavLink></li>
<li><NavLink to="/examples/summary-rows">Summary Rows Example</NavLink></li>
</ul>
<Route path="/examples/basic" component={Basic} />
<Route path="/examples/resizable-cols" component={ResizableCols} />
Expand Down Expand Up @@ -106,6 +108,7 @@ ReactDOM.render((
<Route path="/examples/descendingFirstSortable" component={DescendingFirstSortable} />
<Route path="/examples/selection-range-events" component={SelectionRangeEvents} />
<Route path="/examples/isScrolling" component={IsScrolling} />
<Route path="/examples/summary-rows" component={SummaryRows} />
</HashRouter>
</StrictMode>
), document.getElementById('root'));
Loading

0 comments on commit 0f40988

Please sign in to comment.