mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 07:40:32 +00:00
fix: infinity scrolling of bank account transactions
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
import React from 'react';
|
// @ts-nocheck
|
||||||
import { AppShellProvider, useAppShellContext } from './AppContentShellProvider';
|
import React, { forwardRef, Ref } from 'react';
|
||||||
|
import {
|
||||||
|
AppShellProvider,
|
||||||
|
useAppShellContext,
|
||||||
|
} from './AppContentShellProvider';
|
||||||
import { Box, BoxProps } from '../../Layout';
|
import { Box, BoxProps } from '../../Layout';
|
||||||
import styles from './AppContentShell.module.scss';
|
import styles from './AppContentShell.module.scss';
|
||||||
|
|
||||||
@@ -12,14 +16,18 @@ interface AppContentShellProps {
|
|||||||
hideMain?: boolean;
|
hideMain?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AppContentShell({
|
export const AppContentShell = forwardRef(
|
||||||
|
(
|
||||||
|
{
|
||||||
asideProps,
|
asideProps,
|
||||||
mainProps,
|
mainProps,
|
||||||
topbarOffset = 0,
|
topbarOffset = 0,
|
||||||
hideAside = false,
|
hideAside = false,
|
||||||
hideMain = false,
|
hideMain = false,
|
||||||
...restProps
|
...restProps
|
||||||
}: AppContentShellProps) {
|
}: AppContentShellProps,
|
||||||
|
ref: Ref<HTMLDivElement>,
|
||||||
|
) => {
|
||||||
return (
|
return (
|
||||||
<AppShellProvider
|
<AppShellProvider
|
||||||
mainProps={mainProps}
|
mainProps={mainProps}
|
||||||
@@ -28,34 +36,53 @@ export function AppContentShell({
|
|||||||
hideAside={hideAside}
|
hideAside={hideAside}
|
||||||
hideMain={hideMain}
|
hideMain={hideMain}
|
||||||
>
|
>
|
||||||
<Box {...restProps} className={styles.root} />
|
<Box {...restProps} className={styles.root} ref={ref} />
|
||||||
</AppShellProvider>
|
</AppShellProvider>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
AppContentShell.displayName = 'AppContentShell';
|
||||||
|
|
||||||
interface AppContentShellMainProps extends BoxProps {}
|
interface AppContentShellMainProps extends BoxProps {}
|
||||||
|
|
||||||
function AppContentShellMain({ ...props }: AppContentShellMainProps) {
|
/**
|
||||||
|
* Main content of the app shell.
|
||||||
|
* @param {AppContentShellMainProps} props -
|
||||||
|
* @returns {React.ReactNode}
|
||||||
|
*/
|
||||||
|
const AppContentShellMain = forwardRef(
|
||||||
|
({ ...props }: AppContentShellMainProps, ref: Ref<HTMLDivElement>) => {
|
||||||
const { hideMain } = useAppShellContext();
|
const { hideMain } = useAppShellContext();
|
||||||
|
|
||||||
if (hideMain === true) {
|
if (hideMain === true) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Box {...props} className={styles.main} />;
|
return <Box {...props} className={styles.main} ref={ref} />;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
AppContentShellMain.displayName = 'AppContentShellMain';
|
||||||
|
|
||||||
interface AppContentShellAsideProps extends BoxProps {
|
interface AppContentShellAsideProps extends BoxProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AppContentShellAside({ ...props }: AppContentShellAsideProps) {
|
/**
|
||||||
|
* Aside content of the app shell.
|
||||||
|
* @param {AppContentShellAsideProps} props
|
||||||
|
* @returns {React.ReactNode}
|
||||||
|
*/
|
||||||
|
const AppContentShellAside = forwardRef(
|
||||||
|
({ ...props }: AppContentShellAsideProps, ref: Ref<HTMLDivElement>) => {
|
||||||
const { hideAside } = useAppShellContext();
|
const { hideAside } = useAppShellContext();
|
||||||
|
|
||||||
if (hideAside === true) {
|
if (hideAside === true) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return <Box {...props} className={styles.aside} />;
|
return <Box {...props} className={styles.aside} ref={ref} />;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
AppContentShellAside.displayName = 'AppContentShellAside';
|
||||||
|
|
||||||
AppContentShell.Main = AppContentShellMain;
|
AppContentShell.Main = AppContentShellMain;
|
||||||
AppContentShell.Aside = AppContentShellAside;
|
AppContentShell.Aside = AppContentShellAside;
|
||||||
|
|||||||
@@ -25,14 +25,13 @@ function TableVirtualizedListRow({ index, isScrolling, isVisible, style }) {
|
|||||||
export function TableVirtualizedListRows() {
|
export function TableVirtualizedListRows() {
|
||||||
const {
|
const {
|
||||||
table: { page },
|
table: { page },
|
||||||
props: { vListrowHeight, vListOverscanRowCount },
|
props: { vListrowHeight, vListOverscanRowCount, windowScrollerProps },
|
||||||
} = useContext(TableContext);
|
} = useContext(TableContext);
|
||||||
|
|
||||||
// Dashboard content pane.
|
// Dashboard content pane.
|
||||||
const dashboardContentPane = React.useMemo(
|
const scrollElement =
|
||||||
() => document.querySelector(`.${CLASSES.DASHBOARD_CONTENT_PANE}`),
|
windowScrollerProps?.scrollElement ||
|
||||||
[],
|
document.querySelector(`.${CLASSES.DASHBOARD_CONTENT_PANE}`);
|
||||||
);
|
|
||||||
|
|
||||||
const rowRenderer = React.useCallback(
|
const rowRenderer = React.useCallback(
|
||||||
({ key, ...args }) => <TableVirtualizedListRow {...args} key={key} />,
|
({ key, ...args }) => <TableVirtualizedListRow {...args} key={key} />,
|
||||||
@@ -40,7 +39,7 @@ export function TableVirtualizedListRows() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WindowScroller scrollElement={dashboardContentPane}>
|
<WindowScroller scrollElement={scrollElement}>
|
||||||
{({ height, isScrolling, onChildScroll, scrollTop }) => (
|
{({ height, isScrolling, onChildScroll, scrollTop }) => (
|
||||||
<AutoSizer disableHeight>
|
<AutoSizer disableHeight>
|
||||||
{({ width }) => (
|
{({ width }) => (
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import React from 'react';
|
import React, { forwardRef, Ref } from 'react';
|
||||||
import { HTMLDivProps, Props } from '@blueprintjs/core';
|
import { HTMLDivProps, Props } from '@blueprintjs/core';
|
||||||
|
|
||||||
export interface BoxProps extends Props, HTMLDivProps {
|
export interface BoxProps extends Props, HTMLDivProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Box({ className, ...rest }: BoxProps) {
|
export const Box = forwardRef(
|
||||||
|
({ className, ...rest }: BoxProps, ref: Ref<HTMLDivElement>) => {
|
||||||
const Element = 'div';
|
const Element = 'div';
|
||||||
|
|
||||||
return <Element className={className} {...rest} />;
|
return <Element className={className} ref={ref} {...rest} />;
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
Box.displayName = '@bigcapital/Box';
|
||||||
|
|||||||
@@ -29,7 +29,18 @@ function AccountTransactionsListRoot({
|
|||||||
return (
|
return (
|
||||||
<AccountTransactionsProvider>
|
<AccountTransactionsProvider>
|
||||||
<AppContentShell hideAside={!openMatchingTransactionAside}>
|
<AppContentShell hideAside={!openMatchingTransactionAside}>
|
||||||
<AppContentShell.Main>
|
<AccountTransactionsMain />
|
||||||
|
<AccountTransactionsAside />
|
||||||
|
</AppContentShell>
|
||||||
|
</AccountTransactionsProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccountTransactionsMain() {
|
||||||
|
const { setScrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppContentShell.Main ref={(e) => setScrollableRef(e)}>
|
||||||
<AccountTransactionsActionsBar />
|
<AccountTransactionsActionsBar />
|
||||||
<AccountTransactionsDetailsBar />
|
<AccountTransactionsDetailsBar />
|
||||||
<AccountTransactionsProgressBar />
|
<AccountTransactionsProgressBar />
|
||||||
@@ -42,12 +53,14 @@ function AccountTransactionsListRoot({
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
</DashboardPageContent>
|
</DashboardPageContent>
|
||||||
</AppContentShell.Main>
|
</AppContentShell.Main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AccountTransactionsAside() {
|
||||||
|
return (
|
||||||
<AppContentShell.Aside>
|
<AppContentShell.Aside>
|
||||||
<CategorizeTransactionAside />
|
<CategorizeTransactionAside />
|
||||||
</AppContentShell.Aside>
|
</AppContentShell.Aside>
|
||||||
</AppContentShell>
|
|
||||||
</AccountTransactionsProvider>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { DashboardInsider } from '@/components';
|
import { DashboardInsider } from '@/components';
|
||||||
import { useCashflowAccounts, useAccount } from '@/hooks/query';
|
import { useCashflowAccounts, useAccount } from '@/hooks/query';
|
||||||
@@ -41,6 +41,8 @@ function AccountTransactionsProvider({ query, ...props }) {
|
|||||||
isLoading: isBankAccountMetaSummaryLoading,
|
isLoading: isBankAccountMetaSummaryLoading,
|
||||||
} = useGetBankAccountSummaryMeta(accountId);
|
} = useGetBankAccountSummaryMeta(accountId);
|
||||||
|
|
||||||
|
const [scrollableRef, setScrollableRef] = useState();
|
||||||
|
|
||||||
// Provider payload.
|
// Provider payload.
|
||||||
const provider = {
|
const provider = {
|
||||||
accountId,
|
accountId,
|
||||||
@@ -56,6 +58,9 @@ function AccountTransactionsProvider({ query, ...props }) {
|
|||||||
|
|
||||||
filterTab,
|
filterTab,
|
||||||
setFilterTab,
|
setFilterTab,
|
||||||
|
|
||||||
|
scrollableRef,
|
||||||
|
setScrollableRef
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { TABLES } from '@/constants/tables';
|
|||||||
import { useMemorizedColumnsWidths } from '@/hooks';
|
import { useMemorizedColumnsWidths } from '@/hooks';
|
||||||
import { useExcludedTransactionsColumns } from './_utils';
|
import { useExcludedTransactionsColumns } from './_utils';
|
||||||
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
|
import { useExcludedTransactionsBoot } from './ExcludedTransactionsTableBoot';
|
||||||
|
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||||
|
|
||||||
import { ActionsMenu } from './_components';
|
import { ActionsMenu } from './_components';
|
||||||
import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
import { useUnexcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||||
@@ -37,6 +38,8 @@ function ExcludedTransactionsTableRoot({
|
|||||||
const { mutateAsync: unexcludeBankTransaction } =
|
const { mutateAsync: unexcludeBankTransaction } =
|
||||||
useUnexcludeUncategorizedTransaction();
|
useUnexcludeUncategorizedTransaction();
|
||||||
|
|
||||||
|
const { scrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
// Retrieve table columns.
|
// Retrieve table columns.
|
||||||
const columns = useExcludedTransactionsColumns();
|
const columns = useExcludedTransactionsColumns();
|
||||||
|
|
||||||
@@ -97,6 +100,7 @@ function ExcludedTransactionsTableRoot({
|
|||||||
className="table-constrant"
|
className="table-constrant"
|
||||||
selectionColumn={true}
|
selectionColumn={true}
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
|
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||||
payload={{
|
payload={{
|
||||||
onRestore: handleRestoreClick,
|
onRestore: handleRestoreClick,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { useRecognizedTransactionsBoot } from './RecognizedTransactionsTableBoot
|
|||||||
|
|
||||||
import { ActionsMenu } from './_components';
|
import { ActionsMenu } from './_components';
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
|
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||||
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||||
import {
|
import {
|
||||||
WithBankingActionsProps,
|
WithBankingActionsProps,
|
||||||
@@ -49,6 +50,8 @@ function RecognizedTransactionsTableRoot({
|
|||||||
const [initialColumnsWidths, , handleColumnResizing] =
|
const [initialColumnsWidths, , handleColumnResizing] =
|
||||||
useMemorizedColumnsWidths(TABLES.UNCATEGORIZED_ACCOUNT_TRANSACTIONS);
|
useMemorizedColumnsWidths(TABLES.UNCATEGORIZED_ACCOUNT_TRANSACTIONS);
|
||||||
|
|
||||||
|
const { scrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
// Handle cell click.
|
// Handle cell click.
|
||||||
const handleCellClick = (cell, event) => {
|
const handleCellClick = (cell, event) => {
|
||||||
setUncategorizedTransactionIdForMatching(
|
setUncategorizedTransactionIdForMatching(
|
||||||
@@ -102,6 +105,7 @@ function RecognizedTransactionsTableRoot({
|
|||||||
vListOverscanRowCount={0}
|
vListOverscanRowCount={0}
|
||||||
initialColumnsWidths={initialColumnsWidths}
|
initialColumnsWidths={initialColumnsWidths}
|
||||||
onColumnResizing={handleColumnResizing}
|
onColumnResizing={handleColumnResizing}
|
||||||
|
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||||
noResults={<RecognizedTransactionsTableNoResults />}
|
noResults={<RecognizedTransactionsTableNoResults />}
|
||||||
className="table-constrant"
|
className="table-constrant"
|
||||||
payload={{
|
payload={{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { useMemorizedColumnsWidths } from '@/hooks';
|
|||||||
import { useAccountUncategorizedTransactionsContext } from '../AllTransactionsUncategorizedBoot';
|
import { useAccountUncategorizedTransactionsContext } from '../AllTransactionsUncategorizedBoot';
|
||||||
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
import { useExcludeUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||||
import { useAccountUncategorizedTransactionsColumns } from './hooks';
|
import { useAccountUncategorizedTransactionsColumns } from './hooks';
|
||||||
|
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||||
|
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
import { withBanking } from '../../withBanking';
|
import { withBanking } from '../../withBanking';
|
||||||
@@ -48,6 +49,8 @@ function AccountTransactionsDataTable({
|
|||||||
// Retrieve table columns.
|
// Retrieve table columns.
|
||||||
const columns = useAccountUncategorizedTransactionsColumns();
|
const columns = useAccountUncategorizedTransactionsColumns();
|
||||||
|
|
||||||
|
const { scrollableRef } = useAccountTransactionsContext();
|
||||||
|
|
||||||
// Retrieve list context.
|
// Retrieve list context.
|
||||||
const { uncategorizedTransactions, isUncategorizedTransactionsLoading } =
|
const { uncategorizedTransactions, isUncategorizedTransactionsLoading } =
|
||||||
useAccountUncategorizedTransactionsContext();
|
useAccountUncategorizedTransactionsContext();
|
||||||
@@ -124,6 +127,7 @@ function AccountTransactionsDataTable({
|
|||||||
onCategorize: handleCategorizeBtnClick,
|
onCategorize: handleCategorizeBtnClick,
|
||||||
}}
|
}}
|
||||||
onSelectedRowsChange={handleSelectedRowsChange}
|
onSelectedRowsChange={handleSelectedRowsChange}
|
||||||
|
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||||
className={clsx('table-constrant', styles.table, {
|
className={clsx('table-constrant', styles.table, {
|
||||||
[styles.showCategorizeColumn]: enableMultipleCategorization,
|
[styles.showCategorizeColumn]: enableMultipleCategorization,
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in New Issue
Block a user