Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
69 changes: 69 additions & 0 deletions src/Components/Containers/DataGrid/InfiniteScrollObserver.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { style } from 'typestyle';
interface IProps {
children?: any;
upDatagridHeight?: string;
borderRadius?: string;
borderColor?: string;
onScrollStop: (page?: number, take?: number, skip?: number) => void;
}

export const InfiniteScrollObserver = (props: IProps) => {
const { onScrollStop, borderColor, borderRadius, children, upDatagridHeight } = props;
const [pageNum, setPageNum] = useState(1);
const loader = useRef(null);

const handleObserver = useCallback(entries => {
const target = entries[0];
if (target.isIntersecting) {
setPageNum(prev => prev + 1);
onScrollStop(pageNum);
}
}, []);
useEffect(() => {
const option = {
root: null,
rootMargin: '20px',
threshold: 0,
};
const observer = new IntersectionObserver(handleObserver, option);
if (loader.current) observer.observe(loader.current);
}, [handleObserver]);

return (
<div className={scrollableDataGridStyle(upDatagridHeight, borderRadius, borderColor)}>
{children}
<div ref={loader} />
</div>
);
};

const scrollableDataGridStyle = (upDatagridHeight = '700px', borderRadius?: string, borderColor?: string): string =>
style({
border: 'solid 1px',
borderColor: borderColor,
width: '100%',
borderRadius: borderRadius,
overflowY: 'auto',
maxHeight: upDatagridHeight,
position: 'sticky',
top: 0,
$nest: {
table: {
borderCollapse: 'collapse',
},
thead: {
position: 'sticky',
top: 0,
zIndex: 1000,
},
tbody: {
position: 'sticky',
top: 0,
},
th: {
position: 'sticky',
top: 0,
},
},
});
76 changes: 65 additions & 11 deletions src/Components/Containers/DataGrid/UpDataGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
import * as React from 'react';

import $ from 'jquery';
import classnames from 'classnames';
import $ from 'jquery';
import { media, style } from 'typestyle';

import axios from 'axios';

import UpPagination, { UpPaginationProps } from './UpPagination';
import UpDataGridRowHeader from './UpDataGridRowHeader';
import UpDataGridRow, { ActionFactory } from './UpDataGridRow';
import UpDataGridRowHeader from './UpDataGridRowHeader';
import { ICellFormatter } from './UpDefaultCellFormatter';
import UpPagination, { UpPaginationProps } from './UpPagination';

import UpLoadingIndicator from '../../Display/LoadingIndicator';
import UpButton from '../../Inputs/Button/UpButton';

import { IntentType, WithThemeProps } from '../../../Common/theming/types';
import { ActionType } from '../../../Common/actions';
import UpDefaultTheme, { withTheme } from '../../../Common/theming';
import { IntentType, WithThemeProps } from '../../../Common/theming/types';
import UpDataGridFooter, { UpDataGridFooterProps } from './UpDataGridFooter';
import UpDataGridHeader, { UpDataGridHeaderProps } from './UpDataGridHeader';

import { UpDataGridProvider } from './UpDataGridContext';
import { getTestableComponentProps, TestableComponentProps } from '../../../Common/utils/types';
import { DeviceSmartphones } from '../../../Common/utils/device';
import { IconName } from '../../../Common/theming/icons';
import { isEmpty } from '../../../Common/utils';
import { DetailsData, DetailsType } from './UpDataGridDetails';
import { DeviceSmartphones } from '../../../Common/utils/device';
import { getTestableComponentProps, TestableComponentProps } from '../../../Common/utils/types';
import { InfiniteScrollObserver } from './InfiniteScrollObserver';
import { UpDataGridProvider } from './UpDataGridContext';

const WrapperDataGridStyle = style(
{
Expand Down Expand Up @@ -296,6 +297,9 @@ export interface UpDataGridProps extends TestableComponentProps {
injectRow?: (previous: any, next: any, colum: Column[]) => JSX.Element;
// Event Handler
onSortChange?: (c: Column, dir: SortDirection) => void;
onScrollStop?: (page: number, take: number, skip: number) => void;
upDatagridHeight?: string;
loadOnScroll?: boolean;
onSelectionChange?: (
lastUpdatedRow: Row,
dataSelected: any[],
Expand Down Expand Up @@ -325,6 +329,8 @@ export interface UpDataGridState {
rowsSelected?: Array<Row>;
lastFetchedDataTime?: Date;
data?: any;
currentPage?: number;
refershData?: boolean;
}

export type SortDirection = 'ASC' | 'DESC';
Expand Down Expand Up @@ -412,6 +418,8 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
page: this.props.paginationProps.page || 1,
total: this.props.paginationProps.total,
allRowsSelected: false,
currentPage: 1,
refershData: false,
};

if (this.props.data != null) {
Expand Down Expand Up @@ -470,7 +478,10 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
});
}
// Internal pagination
rows = rows.slice(this.state.skip, this.state.skip + this.state.take);
rows =
!this.state.refershData && this.props.loadOnScroll
? [...this.state.rows, ...rows.slice(this.state.skip, this.state.skip + this.state.take)]
: rows.slice(this.state.skip, this.state.skip + this.state.take);
}
}

Expand Down Expand Up @@ -543,6 +554,21 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
}
};

onScrollStop = (page: number, take: number, skip: number): void => {
const totalPages = Math.ceil(this.state.total / this.state.take);
if (this.state.currentPage < totalPages) {
if (this.props.onScrollStop) this.props.onScrollStop(page, take, skip);
this.setState(
{ currentPage: this.state.currentPage + 1, take, skip, isDataFetching: true, refershData: false },
() => {
if (this.props.dataSource !== undefined) {
this.fetchData();
}
}
);
}
};

onPageChange = (page: number, take: number, skip: number): void => {
if (this.props.paginationProps.onPageChange) this.props.paginationProps.onPageChange(page, take, skip);

Expand Down Expand Up @@ -673,7 +699,7 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
}
});

this.setState({ columns: columns }, () => {
this.setState({ columns: columns, currentPage: 1, refershData: true }, () => {
if (this.props.dataSource != undefined) {
this.fetchData();
}
Expand Down Expand Up @@ -727,6 +753,7 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
take={this.state.take}
total={this.state.total}
onPageChange={this.onPageChange.bind(this)}
loadOnScroll={this.props.loadOnScroll}
{...otherProps}
/>
</div>
Expand Down Expand Up @@ -861,7 +888,34 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
width={320}
height={240}
>
<>
{this.props.loadOnScroll ? (
<InfiniteScrollObserver
onScrollStop={this.onScrollStop.bind(this)}
borderColor={this.props.theme.colorMap.defaultBorder}
borderRadius={this.props.theme.borderRadius}
upDatagridHeight={this.props.upDatagridHeight}
>
<table
ref={r => {
this.refTable = r;
}}
className={classnames('up-data-grid-main', DataGridStyle(this.props))}
>
<UpDataGridRowHeader
isSelectionEnabled={this.props.isSelectionEnabled}
onSelectionChange={this.onSelectionAllChange.bind(this)}
onSortChange={this.onSortChange.bind(this)}
actions={this.props.rowActions}
columns={columns}
displayRowActionsWithinCell={this.props.displayRowActionsWithinCell}
textAlignCells={this.props.textAlignCells}
isAllDataChecked={this.state.allRowsSelected}
isSelectionAllEnabled={!this.props.onlyOneRowCanBeSelected}
/>
<tbody className={classnames('up-data-grid-body', oddEvenStyle)}>{rows}</tbody>
</table>
</InfiniteScrollObserver>
) : (
<table
ref={r => {
this.refTable = r;
Expand All @@ -881,7 +935,7 @@ class UpDataGrid extends React.Component<UpDataGridProps & WithThemeProps, UpDat
/>
<tbody className={classnames('up-data-grid-body', oddEvenStyle)}>{rows}</tbody>
</table>
</>
)}
</UpLoadingIndicator>
<UpDataGridFooter
{...newFooterProps}
Expand Down
91 changes: 54 additions & 37 deletions src/Components/Containers/DataGrid/UpPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export interface UpPaginationProps {
previousLabel?: string;
/** chaine de caractères utilisées comme séparateur dans la pagination*/
paginationNavigationSeparator?: string;
/** if load on scroll enabled use pagination as indicator */
loadOnScroll?: boolean;
/** generate the pages navigation */
generatePagesNavigation?: (page, total, take) => Array<number>;
/** Affihage du nombre de résultats */
Expand Down Expand Up @@ -320,7 +322,7 @@ class UpPagination extends React.Component<UpPaginationProps & WithThemeProps, U
);
}

return (
const paginationNumbers = !this.props.loadOnScroll ? (
<li
key={`page-${index}`}
className={classnames(this.state.page == value ? 'active' : '', paginationItemClass)}
Expand All @@ -330,49 +332,64 @@ class UpPagination extends React.Component<UpPaginationProps & WithThemeProps, U
{value}
</a>
</li>
) : (
<li
key={`page-${index}`}
className={classnames(this.state.page == value ? 'active' : '', paginationItemClass)}
>
<a onClick={e => e.preventDefault()} href="#">
{value}
</a>
</li>
);

return paginationNumbers;
});

pageNumberNavigation = (
<nav className={'up-pagination-nav'}>
<ul className={paginationStyle}>
<li
key={`page-prev`}
className={classnames(
'up-pagination-page-prev',
this.state.page == 1 ? 'disabled' : 'active',
paginationItemClass
)}
onClick={this.goToPreviousPage}
>
<a onClick={e => e.preventDefault()} href="#" aria-label="Previous">
<span
aria-hidden="true"
dangerouslySetInnerHTML={{
__html: this.props.previousLabel,
}}
/>
</a>
</li>
{!this.props.loadOnScroll && (
<li
key={`page-prev`}
className={classnames(
'up-pagination-page-prev',
this.state.page == 1 ? 'disabled' : 'active',
paginationItemClass
)}
onClick={this.goToPreviousPage}
>
<a onClick={e => e.preventDefault()} href="#" aria-label="Previous">
<span
aria-hidden="true"
dangerouslySetInnerHTML={{
__html: this.props.previousLabel,
}}
/>
</a>
</li>
)}
{PageNumber}
<li
key={`page-next`}
className={classnames(
'up-pagination-page-next',
this.state.page == maxPage ? 'disabled' : 'active',
paginationItemClass
)}
onClick={this.goToNextPage}
>
<a href="#" aria-label="Next" onClick={e => e.preventDefault()}>
<span
aria-hidden="true"
dangerouslySetInnerHTML={{
__html: this.props.nextLabel,
}}
/>
</a>
</li>
{!this.props.loadOnScroll && (
<li
key={`page-next`}
className={classnames(
'up-pagination-page-next',
this.state.page == maxPage ? 'disabled' : 'active',
paginationItemClass
)}
onClick={this.goToNextPage}
>
<a href="#" aria-label="Next" onClick={e => e.preventDefault()}>
<span
aria-hidden="true"
dangerouslySetInnerHTML={{
__html: this.props.nextLabel,
}}
/>
</a>
</li>
)}
</ul>
</nav>
);
Expand Down
Loading