feat: add grid all columns search
This commit is contained in:
Родитель
2203cc4a82
Коммит
9d99df0457
|
@ -19,6 +19,8 @@
|
|||
"@progress/kendo-react-inputs": "^3.13.0-dev.202004240541",
|
||||
"@progress/kendo-react-intl": "^3.13.0-dev.202004240541",
|
||||
"@progress/kendo-react-layout": "^3.13.0-dev.202004240541",
|
||||
"@progress/kendo-react-pdf": "^3.13.0-dev.202004240541",
|
||||
"@progress/kendo-react-excel-export": "^3.13.0-dev.202004240541",
|
||||
"@progress/kendo-react-scheduler": "^3.12.0",
|
||||
"@progress/kendo-react-upload": "^3.13.0-dev.202004240541",
|
||||
"@progress/kendo-theme-default": "^4.17.0",
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
import React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
|
||||
import { Grid as KendoGrid, GridColumn, GridColumnMenuSort, GridColumnMenuFilter } from '@progress/kendo-react-grid';
|
||||
import { Grid as KendoGrid, GridColumn, GridColumnMenuSort, GridColumnMenuFilter, GridToolbar } from '@progress/kendo-react-grid';
|
||||
import { Button } from '@progress/kendo-react-buttons'
|
||||
import { GridPDFExport } from '@progress/kendo-react-pdf';
|
||||
import { ExcelExport } from '@progress/kendo-react-excel-export';
|
||||
import { process } from '@progress/kendo-data-query';
|
||||
import { Input } from '@progress/kendo-react-inputs';
|
||||
|
||||
export const Column = GridColumn;
|
||||
|
||||
|
@ -19,29 +23,107 @@ export const ColumnMenu = (props) => {
|
|||
export const Grid = (props) => {
|
||||
const { data, onDataChange, ...others } = props;
|
||||
|
||||
const excelExportRef = React.useRef(null);
|
||||
const pdfExportRef = React.useRef(null);
|
||||
|
||||
const [isPdfExporting, setIsPdfExporting] = React.useState(false);
|
||||
const [take, setTake] = React.useState(10);
|
||||
const [skip, setSkip] = React.useState(0);
|
||||
const [sort, setSort] = React.useState([]);
|
||||
const [group, setGroup] = React.useState([]);
|
||||
const [filter, setFilter] = React.useState(null);
|
||||
const lastSelectedIndexRef = React.useRef(0);
|
||||
const [allColumnFilter, setAllColumnFilter] = React.useState('');
|
||||
|
||||
const dataState = {
|
||||
take,
|
||||
skip,
|
||||
sort,
|
||||
group
|
||||
group,
|
||||
filter
|
||||
};
|
||||
|
||||
const textColumns = props.children.map(col => {
|
||||
if (col.props.children) {
|
||||
return col.props.children.map(child => {
|
||||
if (!child.props.filter || child.props.filter === "text") {
|
||||
return child.props.field;
|
||||
}
|
||||
});
|
||||
} else if (col.props.field) {
|
||||
if (!col.props.filter || col.props.filter === "text") {
|
||||
return col.props.field;
|
||||
}
|
||||
}
|
||||
})
|
||||
.flat()
|
||||
.filter(field => field);
|
||||
|
||||
const allColumnsFilters = textColumns.map(column => ({
|
||||
field: column,
|
||||
operator: 'contains',
|
||||
value: allColumnFilter
|
||||
}));
|
||||
|
||||
const allColumnFilteredData = allColumnFilter ?
|
||||
process(data, {filter: { logic: "or", filters: allColumnsFilters }}).data :
|
||||
data;
|
||||
|
||||
const processedData = process(allColumnFilteredData, dataState);
|
||||
|
||||
React.useEffect(
|
||||
() => {
|
||||
if (!processedData.data.length) {
|
||||
setSkip(0);
|
||||
}
|
||||
},
|
||||
[processedData]
|
||||
)
|
||||
|
||||
const onDataStateChange = React.useCallback(
|
||||
(event) => {
|
||||
setTake(event.data.take);
|
||||
setSkip(event.data.skip);
|
||||
setSort(event.data.sort);
|
||||
setGroup(event.data.group)
|
||||
setGroup(event.data.group);
|
||||
setFilter(event.data.filter);
|
||||
},
|
||||
[setTake, setSkip, setSort, setGroup]
|
||||
);
|
||||
|
||||
const onExcelExport = React.useCallback(
|
||||
() => {
|
||||
if (excelExportRef.current) {
|
||||
excelExportRef.current.save();
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const onPdfExportDone = React.useCallback(
|
||||
() => {
|
||||
setIsPdfExporting(false);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const onAllColumnFilterChange = React.useCallback(
|
||||
(event) => {
|
||||
setAllColumnFilter(event.value);
|
||||
},
|
||||
[setAllColumnFilter]
|
||||
);
|
||||
|
||||
const onPdfExport = React.useCallback(
|
||||
() => {
|
||||
if (pdfExportRef.current) {
|
||||
setIsPdfExporting(true);
|
||||
pdfExportRef.current.save(processedData.data, onPdfExportDone);
|
||||
}
|
||||
},
|
||||
[processedData, onPdfExportDone]
|
||||
);
|
||||
|
||||
const onSelectionChange = React.useCallback(
|
||||
(event) => {
|
||||
let last = lastSelectedIndexRef.current;
|
||||
|
@ -82,7 +164,7 @@ export const Grid = (props) => {
|
|||
[data, onDataChange]
|
||||
);
|
||||
|
||||
return (
|
||||
const GridElement = (
|
||||
<KendoGrid
|
||||
{...dataState}
|
||||
{...others}
|
||||
|
@ -92,12 +174,26 @@ export const Grid = (props) => {
|
|||
groupable
|
||||
selectedField={'selected'}
|
||||
|
||||
data={process(data, dataState)}
|
||||
data={processedData}
|
||||
onDataStateChange={onDataStateChange}
|
||||
|
||||
onSelectionChange={onSelectionChange}
|
||||
onHeaderSelectionChange={onHeaderSelectionChange}
|
||||
>
|
||||
<GridToolbar>
|
||||
<Input value={allColumnFilter} onChange={onAllColumnFilterChange} placeholder={'Search in all columns...'} />
|
||||
<Button
|
||||
onClick={onExcelExport}
|
||||
>
|
||||
Export to Excel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onPdfExport}
|
||||
disabled={isPdfExporting}
|
||||
>
|
||||
Export PDF
|
||||
</Button>
|
||||
</GridToolbar>
|
||||
<Column
|
||||
field={'selected'}
|
||||
width={50}
|
||||
|
@ -109,6 +205,18 @@ export const Grid = (props) => {
|
|||
{props.children}
|
||||
</KendoGrid>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ExcelExport data={processedData.data} ref={excelExportRef}>
|
||||
{ GridElement }
|
||||
</ExcelExport>
|
||||
<GridPDFExport ref={pdfExportRef}>
|
||||
{ GridElement }
|
||||
</GridPDFExport>
|
||||
</>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
Grid.displayName = 'Grid';
|
||||
|
|
|
@ -107,18 +107,18 @@ const Dashboard = () => {
|
|||
<span></span>
|
||||
<div className="card-component">
|
||||
<Grid data={filterBy(data, gridFilterExpression)} style={{ height: 480, maxWidth: window.innerWidth - 20 }} onDataChange={data => setData(data)}>
|
||||
<Column title={localizationService.toLanguageString('custom.employee')}>
|
||||
<Column title={localizationService.toLanguageString('custom.employee')} groupable={false}>
|
||||
<Column field={'fullName'} title={localizationService.toLanguageString('custom.contactName')} columnMenu={ColumnMenu} width={230} cell={FullNameCell} />
|
||||
<Column field={'jobTitle'} title={localizationService.toLanguageString('custom.jobTitle')} columnMenu={ColumnMenu} width={230} />
|
||||
<Column field={'country'} title={localizationService.toLanguageString('custom.country')} columnMenu={ColumnMenu} width={100} cell={FlagCell} />
|
||||
<Column field={'isOnline'} title={localizationService.toLanguageString('custom.status')} columnMenu={ColumnMenu} width={100} cell={OnlineCell} />
|
||||
<Column field={'isOnline'} title={localizationService.toLanguageString('custom.status')} columnMenu={ColumnMenu} width={100} cell={OnlineCell} filter={'boolean'} />
|
||||
</Column>
|
||||
<Column title={localizationService.toLanguageString('custom.performance')}>
|
||||
<Column field={'rating'} title={localizationService.toLanguageString('custom.rating')} columnMenu={ColumnMenu} width={110} cell={RatingCell} />
|
||||
<Column field={'target'} title={localizationService.toLanguageString('custom.engagement')} columnMenu={ColumnMenu} width={200} cell={EngagementCell} />
|
||||
<Column field={'budget'} title={localizationService.toLanguageString('custom.budget')} columnMenu={ColumnMenu} width={100} cell={CurrencyCell} />
|
||||
<Column title={localizationService.toLanguageString('custom.performance')} groupable={false}>
|
||||
<Column field={'rating'} title={localizationService.toLanguageString('custom.rating')} columnMenu={ColumnMenu} width={110} cell={RatingCell} filter={'numeric'} />
|
||||
<Column field={'target'} title={localizationService.toLanguageString('custom.engagement')} columnMenu={ColumnMenu} width={200} cell={EngagementCell} filter={'numeric'} />
|
||||
<Column field={'budget'} title={localizationService.toLanguageString('custom.budget')} columnMenu={ColumnMenu} width={100} cell={CurrencyCell} filter={'numeric'} />
|
||||
</Column>
|
||||
<Column title={localizationService.toLanguageString('custom.contacts')}>
|
||||
<Column title={localizationService.toLanguageString('custom.contacts')} groupable={false}>
|
||||
<Column field={'phone'} title={localizationService.toLanguageString('custom.phone')} columnMenu={ColumnMenu} width={130} />
|
||||
<Column field={'address'} title={localizationService.toLanguageString('custom.address')} columnMenu={ColumnMenu} width={200} />
|
||||
</Column>
|
||||
|
|
Загрузка…
Ссылка в новой задаче