import React, { useCallback, useState } from 'react';
import DataGrid, {
Column, FilterRow, Selection, Pager, Lookup,
} from 'devextreme-react/data-grid';
import type { DataGridTypes } from 'devextreme-react/data-grid';
import Button from 'devextreme-react/button';
import { query } from 'devextreme-react/common/data';
import { createStore } from 'devextreme-aspnet-data-nojquery';
const MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
const url = 'https://js.devexpress.com/Demos/NetCore/api/TreeListTasks';
const tasksDataSource = createStore({
key: 'Task_ID',
loadUrl: `${url}/Tasks`,
onBeforeSend(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
});
const employeesDataSource = createStore({
key: 'ID',
loadUrl: `${url}/TaskEmployees`,
onBeforeSend(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
});
const selectionFilter = ['Task_Status', '=', 'Completed'];
let dataGrid: DataGridTypes.InitializedEvent['component'];
const App = () => {
const [taskCount, setTaskCount] = useState(0);
const [peopleCount, setPeopleCount] = useState(0);
const [avgDuration, setAvgDuration] = useState(0);
const calculateStatistics = useCallback(async () => {
const selectedItems = await dataGrid?.getSelectedRowsData() ?? [];
const totalDuration = selectedItems.reduce((currentValue: number, item: { Task_Due_Date: string; Task_Start_Date: string; }) => {
const dueDateTime = new Date(item.Task_Due_Date).getTime();
const startDateTime = new Date(item.Task_Start_Date).getTime();
const duration = dueDateTime - startDateTime;
return currentValue + duration;
}, 0);
const averageDurationInDays = totalDuration / MILLISECONDS_IN_DAY / selectedItems.length;
setTaskCount(selectedItems.length);
setPeopleCount(
query(selectedItems)
.groupBy('Task_Assigned_Employee_ID')
.toArray().length,
);
setAvgDuration(Math.round(averageDurationInDays) || 0);
}, []);
const onInitialized = useCallback((e: DataGridTypes.InitializedEvent) => {
dataGrid = e.component;
calculateStatistics();
}, [calculateStatistics]);
return (
<div>
<DataGrid
id="grid-container"
dataSource={tasksDataSource}
remoteOperations={true}
showBorders={true}
defaultSelectionFilter={selectionFilter}
onInitialized={onInitialized}
>
<Selection mode="multiple" deferred={true} />
<FilterRow visible={true} />
<Pager visible={true} />
<Column caption="Subject" dataField="Task_Subject" />
<Column
caption="Start Date"
dataField="Task_Start_Date"
width="auto"
dataType="date"
/>
<Column
caption="Due Date"
dataField="Task_Due_Date"
width="auto"
dataType="date"
/>
<Column
caption="Assigned To"
dataField="Task_Assigned_Employee_ID"
width="auto"
allowSorting={false}
>
<Lookup
dataSource={employeesDataSource}
valueExpr="ID"
displayExpr="Name"
/>
</Column>
<Column caption="Status" width="auto" dataField="Task_Status" />
</DataGrid>
<div className="selection-summary center">
<Button
id="calculateButton"
text="Get statistics on the selected tasks"
type="default"
onClick={calculateStatistics}
/>
<div>
<div className="column">
<span className="text count">Task count:</span>
<span className="value">{taskCount}</span>
</div>
<div className="column">
<span className="text people-count">People assigned:</span>
<span className="value">{peopleCount}</span>
</div>
<div className="column">
<span className="text avg-duration">Average task duration (days):</span>
<span className="value">{avgDuration}</span>
</div>
</div>
</div>
</div>
);
};
export default App;
import React, { useCallback, useState } from 'react';
import DataGrid, {
Column, FilterRow, Selection, Pager, Lookup,
} from 'devextreme-react/data-grid';
import Button from 'devextreme-react/button';
import { query } from 'devextreme-react/common/data';
import { createStore } from 'devextreme-aspnet-data-nojquery';
const MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
const url = 'https://js.devexpress.com/Demos/NetCore/api/TreeListTasks';
const tasksDataSource = createStore({
key: 'Task_ID',
loadUrl: `${url}/Tasks`,
onBeforeSend(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
});
const employeesDataSource = createStore({
key: 'ID',
loadUrl: `${url}/TaskEmployees`,
onBeforeSend(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
});
const selectionFilter = ['Task_Status', '=', 'Completed'];
let dataGrid;
const App = () => {
const [taskCount, setTaskCount] = useState(0);
const [peopleCount, setPeopleCount] = useState(0);
const [avgDuration, setAvgDuration] = useState(0);
const calculateStatistics = useCallback(async () => {
const selectedItems = (await dataGrid?.getSelectedRowsData()) ?? [];
const totalDuration = selectedItems.reduce((currentValue, item) => {
const dueDateTime = new Date(item.Task_Due_Date).getTime();
const startDateTime = new Date(item.Task_Start_Date).getTime();
const duration = dueDateTime - startDateTime;
return currentValue + duration;
}, 0);
const averageDurationInDays = totalDuration / MILLISECONDS_IN_DAY / selectedItems.length;
setTaskCount(selectedItems.length);
setPeopleCount(query(selectedItems).groupBy('Task_Assigned_Employee_ID').toArray().length);
setAvgDuration(Math.round(averageDurationInDays) || 0);
}, []);
const onInitialized = useCallback(
(e) => {
dataGrid = e.component;
calculateStatistics();
},
[calculateStatistics],
);
return (
<div>
<DataGrid
id="grid-container"
dataSource={tasksDataSource}
remoteOperations={true}
showBorders={true}
defaultSelectionFilter={selectionFilter}
onInitialized={onInitialized}
>
<Selection
mode="multiple"
deferred={true}
/>
<FilterRow visible={true} />
<Pager visible={true} />
<Column
caption="Subject"
dataField="Task_Subject"
/>
<Column
caption="Start Date"
dataField="Task_Start_Date"
width="auto"
dataType="date"
/>
<Column
caption="Due Date"
dataField="Task_Due_Date"
width="auto"
dataType="date"
/>
<Column
caption="Assigned To"
dataField="Task_Assigned_Employee_ID"
width="auto"
allowSorting={false}
>
<Lookup
dataSource={employeesDataSource}
valueExpr="ID"
displayExpr="Name"
/>
</Column>
<Column
caption="Status"
width="auto"
dataField="Task_Status"
/>
</DataGrid>
<div className="selection-summary center">
<Button
id="calculateButton"
text="Get statistics on the selected tasks"
type="default"
onClick={calculateStatistics}
/>
<div>
<div className="column">
<span className="text count">Task count:</span>
<span className="value">{taskCount}</span>
</div>
<div className="column">
<span className="text people-count">People assigned:</span>
<span className="value">{peopleCount}</span>
</div>
<div className="column">
<span className="text avg-duration">Average task duration (days):</span>
<span className="value">{avgDuration}</span>
</div>
</div>
</div>
</div>
);
};
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
<!DOCTYPE html>
<html lang="en">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/26.1.5/css/dx.light.css" />
<link rel="stylesheet" type="text/css" href="./bundle.css" />
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
<script src="bundles/vendor/react.vendor.js"></script>
<script src="./bundle.js"></script>
</body>
</html>
#grid-container {
height: 400px;
}
.center {
text-align: center;
}
.selection-summary {
border: 1px solid rgba(161, 161, 161, 0.2);
padding: 25px;
}
.column {
margin: 20px 30px 0 0;
display: inline-block;
white-space: nowrap;
text-align: right;
}
.value {
font-size: 40px;
display: inline-block;
vertical-align: middle;
}
.text {
text-align: left;
white-space: normal;
display: inline-block;
vertical-align: middle;
}
.avg-duration {
width: 100px;
}
.count {
width: 40px;
}
.people-count {
width: 65px;
}