feat: export reports csv and xlsx (#286)

This commit is contained in:
Ahmed Bouhuolia
2023-11-28 19:53:13 +02:00
committed by GitHub
parent 151aff4c8e
commit d15c5890ed
125 changed files with 4674 additions and 934 deletions

View File

@@ -15,6 +15,7 @@ import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
import { APAgingSummaryExportMenu } from './components';
import withAPAgingSummary from './withAPAgingSummary';
import withAPAgingSummaryActions from './withAPAgingSummaryActions';
@@ -106,11 +107,18 @@ function APAgingSummaryActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<APAgingSummaryExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -27,6 +27,7 @@ function APAgingSummaryProvider({ filter, ...props }) {
isAPAgingLoading,
isAPAgingFetching,
refetch,
query,
};
return (

View File

@@ -1,10 +1,23 @@
// @ts-nocheck
import React, { useMemo } from 'react';
import { useRef } from 'react';
import classNames from 'classnames';
import { If } from '@/components';
import { AppToaster, If, Stack } from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { useAPAgingSummaryContext } from './APAgingSummaryProvider';
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
import {
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import {
useAPAgingSheetCsvExport,
useAPAgingSheetXlsxExport,
} from '@/hooks/query';
/**
* Retrieve AP aging summary columns.
@@ -29,3 +42,87 @@ export function APAgingSummarySheetLoadingBar() {
</If>
);
}
/**
* A/P aging summary export menu.
* @returns {JSX.Element}
*/
export function APAgingSummaryExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useAPAgingSummaryContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useAPAgingSheetXlsxExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useAPAgingSheetCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -19,6 +19,7 @@ import withARAgingSummaryActions from './withARAgingSummaryActions';
import withARAgingSummary from './withARAgingSummary';
import { compose, safeInvoke } from '@/utils';
import { ARAgingSummaryExportMenu } from './components';
/**
* A/R Aging summary sheet - Actions bar.
@@ -107,11 +108,18 @@ function ARAgingSummaryActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<ARAgingSummaryExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,10 +1,23 @@
// @ts-nocheck
import React from 'react';
import React, { useRef } from 'react';
import classNames from 'classnames';
import {
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import { useARAgingSummaryContext } from './ARAgingSummaryProvider';
import { If, FormattedMessage as T } from '@/components';
import { AppToaster, If, Stack, FormattedMessage as T } from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns';
import {
useARAgingSheetCsvExport,
useARAgingSheetXlsxExport,
} from '@/hooks/query';
/**
* Retrieve AR aging summary columns.
@@ -29,3 +42,88 @@ export function ARAgingSummarySheetLoadingBar() {
</If>
);
}
/**
* A/R aging summary export menu.
* @returns {JSX.Element}
*/
export function ARAgingSummaryExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useARAgingSummaryContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useARAgingSheetXlsxExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useARAgingSheetCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -1,5 +1,4 @@
// @ts-nocheck
import React from 'react';
import {
NavbarGroup,
Button,
@@ -13,11 +12,12 @@ import classNames from 'classnames';
import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
import { BalanceSheetExportMenu } from './components';
import { compose, saveInvoke } from '@/utils';
import { useBalanceSheetContext } from './BalanceSheetProvider';
import withBalanceSheet from './withBalanceSheet';
import withBalanceSheetActions from './withBalanceSheetActions';
import { compose, saveInvoke } from '@/utils';
/**
* Balance sheet - actions bar.
@@ -114,11 +114,18 @@ function BalanceSheetActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<BalanceSheetExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,13 +1,32 @@
// @ts-nocheck
import React from 'react';
import { Button } from '@blueprintjs/core';
import React, { useRef } from 'react';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import classNames from 'classnames';
import { FormattedMessage as T, Icon, If } from '@/components';
import {
FormattedMessage as T,
Icon,
If,
Stack,
AppToaster,
} from '@/components';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { useBalanceSheetContext } from './BalanceSheetProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import { dynamicColumns } from './dynamicColumns';
import {
useBalanceSheetCsvExport,
useBalanceSheetXlsxExport,
} from '@/hooks/query';
/**
* Balance sheet alerts.
@@ -66,3 +85,88 @@ export const useBalanceSheetColumns = () => {
[table],
);
};
/**
* Retrieves the balance sheet export menu.
* @returns {JSX.Element}
*/
export const BalanceSheetExportMenu = () => {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useBalanceSheetContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useBalanceSheetXlsxExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useBalanceSheetCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport().then(() => {});
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport().then(() => {});
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
};

View File

@@ -19,6 +19,7 @@ import withCashFlowStatement from './withCashFlowStatement';
import withCashFlowStatementActions from './withCashFlowStatementActions';
import { compose, saveInvoke } from '@/utils';
import { CashflowSheetExportMenu } from './components';
/**
* Cash flow statement actions bar.
@@ -115,11 +116,18 @@ function CashFlowStatementActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<CashflowSheetExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,8 +1,27 @@
// @ts-nocheck
import React from 'react';
import { Button } from '@blueprintjs/core';
import React, { useRef } from 'react';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import classNames from 'classnames';
import { Icon, If, FormattedMessage as T } from '@/components';
import {
AppToaster,
Icon,
If,
Stack,
FormattedMessage as T,
} from '@/components';
import {
useCashFlowStatementCsvExport,
useCashFlowStatementXlsxExport,
} from '@/hooks/query';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { dynamicColumns } from './dynamicColumns';
@@ -65,3 +84,88 @@ export function CashFlowStatementAlerts() {
</FinancialComputeAlert>
);
}
/**
* Cashflow sheet export menu.
* @returns {JSX.Element}
*/
export function CashflowSheetExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useCashFlowStatementContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useCashFlowStatementXlsxExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useCashFlowStatementCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -17,6 +17,7 @@ import withCustomersBalanceSummary from './withCustomersBalanceSummary';
import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions';
import { useCustomersBalanceSummaryContext } from './CustomersBalanceSummaryProvider';
import { compose, saveInvoke } from '@/utils';
import { CustomerBalanceSummaryExportMenu } from './components';
/**
* customer balance summary action bar.
@@ -35,7 +36,7 @@ function CustomersBalanceSummaryActionsBar({
const { refetch, isCustomersBalanceLoading } =
useCustomersBalanceSummaryContext();
// handle filter toggle click.
// Handle filter toggle click.
const handleFilterToggleClick = () => {
toggleCustomerBalanceFilterDrawer();
};
@@ -112,11 +113,18 @@ function CustomersBalanceSummaryActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<CustomerBalanceSummaryExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -31,6 +31,7 @@ function CustomersBalanceSummaryProvider({ filter, ...props }) {
isCustomersBalanceLoading,
refetch,
query
};
return (
<FinancialReportPage name={'customers-balance-summary'}>

View File

@@ -32,7 +32,7 @@ export default function CustomersBalanceSummaryTable({
>
<CustomerBalanceDataTable
columns={columns}
data={table.data}
data={table.rows}
rowClassNames={tableRowTypesToClassnames}
noInitialFetch={true}
sticky={true}

View File

@@ -1,13 +1,25 @@
// @ts-nocheck
import React from 'react';
import React, { useRef } from 'react';
import intl from 'react-intl-universal';
import * as R from 'ramda';
import classNames from 'classnames';
import { If } from '@/components';
import { AppToaster, If, Stack } from '@/components';
import { Align } from '@/constants';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { useCustomersBalanceSummaryContext } from './CustomersBalanceSummaryProvider';
import {
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import {
useCustomerBalanceSummaryCsvExport,
useCustomerBalanceSummaryXlsxExport,
} from '@/hooks/query';
/**
* Retrieve customers balance summary columns.
@@ -79,3 +91,89 @@ export function CustomersBalanceLoadingBar() {
</If>
);
}
/**
* Customer balance summary export menu.
*/
export function CustomerBalanceSummaryExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useCustomersBalanceSummaryContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useCustomerBalanceSummaryXlsxExport(
query,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Export the report to csv.
const { mutateAsync: csvExport } = useCustomerBalanceSummaryCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -9,9 +9,10 @@ import {
PopoverInteractionKind,
Position,
} from '@blueprintjs/core';
import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import classNames from 'classnames';
import { DashboardActionsBar, FormattedMessage as T, Icon } from '@/components';
import { CustomersTransactionsExportMenu } from './components';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
import { useCustomersTransactionsContext } from './CustomersTransactionsProvider';
@@ -114,11 +115,18 @@ function CustomersTransactionsActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<CustomersTransactionsExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,12 +1,24 @@
// @ts-nocheck
import React from 'react';
import React, { useRef } from 'react';
import intl from 'react-intl-universal';
import { If } from '@/components';
import { AppToaster, If, Stack } from '@/components';
import { Align } from '@/constants';
import { getColumnWidth } from '@/utils';
import { useCustomersTransactionsContext } from './CustomersTransactionsProvider';
import FinancialLoadingBar from '../FinancialLoadingBar';
import {
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import {
useCustomersTransactionsCsvExport,
useCustomersTransactionsXlsxExport,
} from '@/hooks/query';
import classNames from 'classnames';
/**
* Retrieve customers transactions columns.
@@ -92,3 +104,91 @@ export function CustomersTransactionsLoadingBar() {
</If>
);
}
/**
* Customers transactions export menu.
* @returns {JSX.Element}
*/
export function CustomersTransactionsExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useCustomersTransactionsContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useCustomersTransactionsXlsxExport(
query,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Export the report to csv.
const { mutateAsync: csvExport } = useCustomersTransactionsCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -13,6 +13,7 @@ import { DashboardActionsBar, Icon, FormattedMessage as T } from '@/components';
import classNames from 'classnames';
import NumberFormatDropdown from '@/components/NumberFormatDropdown';
import { InventoryItemDetailsExportMenu } from './components';
import { useInventoryItemDetailsContext } from './InventoryItemDetailsProvider';
import withInventoryItemDetails from './withInventoryItemDetails';
@@ -112,11 +113,18 @@ function InventoryItemDetailsActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<InventoryItemDetailsExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,12 +1,32 @@
// @ts-nocheck
import React from 'react';
import { Button } from '@blueprintjs/core';
import { Icon, If, FormattedMessage as T } from '@/components';
import React, { useRef } from 'react';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import classNames from 'classnames';
import {
AppToaster,
Icon,
If,
Stack,
FormattedMessage as T,
} from '@/components';
import { dynamicColumns } from './utils';
import FinancialLoadingBar from '../FinancialLoadingBar';
import {
useInventoryItemDetailsCsvExport,
useInventoryItemDetailsXlsxExport,
} from '@/hooks/query';
import { useInventoryItemDetailsContext } from './InventoryItemDetailsProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import { useInventoryValuationHttpQuery } from './utils2';
/**
* Retrieve inventory item details columns.
@@ -70,3 +90,94 @@ export function InventoryItemDetailsAlerts() {
</FinancialComputeAlert>
);
}
/**
* Inventory item details export menu.
* @returns {JSX.Element}
*/
export function InventoryItemDetailsExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const httpQuery = useInventoryValuationHttpQuery();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useInventoryItemDetailsXlsxExport(
httpQuery,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Export the report to csv.
const { mutateAsync: csvExport } = useInventoryItemDetailsCsvExport(
httpQuery,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -7,6 +7,7 @@ import intl from 'react-intl-universal';
import { useAppQueryString } from '@/hooks';
import { transformToForm } from '@/utils';
import { transformFilterFormToQuery } from '../common';
/**
* Retrieves inventory item details default query.
@@ -73,3 +74,13 @@ export const useInventoryValuationQuery = () => {
setLocationQuery,
};
};
/**
* Retrieves the inventory valuation http query.
* @returns {Object}
*/
export const useInventoryValuationHttpQuery = () => {
const { query } = useInventoryValuationQuery();
return React.useMemo(() => transformFilterFormToQuery(query), [query]);
};

View File

@@ -19,6 +19,7 @@ import withProfitLoss from './withProfitLoss';
import { compose, saveInvoke } from '@/utils';
import { useProfitLossSheetContext } from './ProfitLossProvider';
import { ProfitLossSheetExportMenu } from './components';
/**
* Profit/Loss sheet actions bar.
@@ -110,11 +111,18 @@ function ProfitLossActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<ProfitLossSheetExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,5 +1,5 @@
// @ts-nocheck
import React, { createContext, useContext } from 'react';
import React, { createContext, useContext, useMemo } from 'react';
import FinancialReportPage from '../FinancialReportPage';
import { useProfitLossSheet } from '@/hooks/query';
import { transformFilterFormToQuery } from '../common';
@@ -11,15 +11,18 @@ const ProfitLossSheetContext = createContext();
* @returns {React.JSX}
*/
function ProfitLossSheetProvider({ query, ...props }) {
const innerQuery = useMemo(() => {
return transformFilterFormToQuery(query);
}, [query]);
const {
data: profitLossSheet,
isFetching,
isLoading,
refetch,
} = useProfitLossSheet(
{
...transformFilterFormToQuery(query),
},
innerQuery,
{ keepPreviousData: true },
);
@@ -28,6 +31,7 @@ function ProfitLossSheetProvider({ query, ...props }) {
isLoading,
isFetching,
sheetRefetch: refetch,
query: innerQuery
};
return (

View File

@@ -1,11 +1,29 @@
// @ts-nocheck
import React from 'react';
import { Button } from '@blueprintjs/core';
import { Icon, If, FormattedMessage as T } from '@/components';
import React, { useRef } from 'react';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import {
AppToaster,
Icon,
If,
Stack,
FormattedMessage as T,
} from '@/components';
import { useProfitLossSheetContext } from './ProfitLossProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import FinancialLoadingBar from '../FinancialLoadingBar';
import {
useProfitLossSheetCsvExport,
useProfitLossSheetXlsxExport,
} from '@/hooks/query';
import classNames from 'classnames';
/**
* Profit/loss sheet loading bar.
@@ -50,3 +68,87 @@ export function ProfitLossSheetAlerts() {
</FinancialComputeAlert>
);
}
/**
* Profit/loss sheet export menu.
*/
export const ProfitLossSheetExportMenu = () => {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useProfitLossSheetContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useProfitLossSheetXlsxExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useProfitLossSheetCsvExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
};

View File

@@ -18,6 +18,7 @@ import { compose, saveInvoke } from '@/utils';
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
import withSalesTaxLiabilitySummary from './withSalesTaxLiabilitySummary';
import withSalesTaxLiabilitySummaryActions from './withSalesTaxLiabilitySummaryActions';
import { SalesTaxLiabilityExportMenu } from './components';
/**
* Sales tax liability summary - actions bar.
@@ -113,11 +114,18 @@ function SalesTaxLiabilitySummaryActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<SalesTaxLiabilityExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,8 +1,22 @@
// @ts-nocheck
import React from 'react';
import { useRef } from 'react';
import classNames from 'classnames';
import {
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import { useSalesTaxLiabilitySummaryContext } from './SalesTaxLiabilitySummaryBoot';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { AppToaster, Stack } from '@/components';
import {
useSalesTaxLiabilitySummaryCsvExport,
useSalesTaxLiabilitySummaryXlsxExport,
} from '@/hooks/query';
import { useSalesByItemsContext } from '../SalesByItems/SalesByItemProvider';
/**
* Sales tax liability summary loading bar.
@@ -15,3 +29,94 @@ export function SalesTaxLiabilitySummaryLoadingBar() {
}
return <FinancialLoadingBar />;
}
/**
*
* @returns {JSX.Element}
*/
export function SalesTaxLiabilityExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useSalesTaxLiabilitySummaryContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useSalesTaxLiabilitySummaryXlsxExport(
query,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Export the report to csv.
const { mutateAsync: csvExport } = useSalesTaxLiabilitySummaryCsvExport(
query,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -18,6 +18,7 @@ import withTrialBalance from './withTrialBalance';
import withTrialBalanceActions from './withTrialBalanceActions';
import { compose, saveInvoke } from '@/utils';
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
import { TrialBalanceSheetExportMenu } from './components';
function TrialBalanceActionsBar({
// #withTrialBalance
@@ -109,11 +110,18 @@ function TrialBalanceActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<TrialBalanceSheetExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,9 +1,30 @@
// @ts-nocheck
import { Button } from '@blueprintjs/core';
import { If, Icon, FormattedMessage as T } from '@/components';
import { useRef } from 'react';
import {
Button,
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import classNames from 'classnames';
import {
If,
Icon,
FormattedMessage as T,
Stack,
AppToaster,
} from '@/components';
import { useTrialBalanceSheetContext } from './TrialBalanceProvider';
import { FinancialComputeAlert } from '../FinancialReportPage';
import FinancialLoadingBar from '../FinancialLoadingBar';
import {
useTrialBalanceSheetCsvExport,
useTrialBalanceSheetXlsxExport,
} from '@/hooks/query';
import { useTrialBalanceSheetHttpQuery } from './utils';
/**
* Trial balance sheet progress loading bar.
@@ -22,11 +43,8 @@ export function TrialBalanceSheetLoadingBar() {
* Trial balance sheet alerts.
*/
export function TrialBalanceSheetAlerts() {
const {
trialBalanceSheet,
isLoading,
refetchSheet,
} = useTrialBalanceSheetContext();
const { trialBalanceSheet, isLoading, refetchSheet } =
useTrialBalanceSheetContext();
// Handle refetch the sheet.
const handleRecalcReport = () => {
@@ -52,3 +70,89 @@ export function TrialBalanceSheetAlerts() {
</FinancialComputeAlert>
);
}
/**
* Trial balance sheet export menu.
*/
export const TrialBalanceSheetExportMenu = () => {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const httpQuery = useTrialBalanceSheetHttpQuery();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useTrialBalanceSheetXlsxExport(
httpQuery,
{
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
},
);
// Export the report to csv.
const { mutateAsync: csvExport } = useTrialBalanceSheetCsvExport(httpQuery, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
};

View File

@@ -5,6 +5,7 @@ import { castArray } from 'lodash';
import { useAppQueryString } from '@/hooks';
import { transformToForm } from '@/utils';
import { transformFilterFormToQuery } from '../common';
/**
* Retrieves the default trial balance query.
@@ -56,3 +57,13 @@ export const useTrialBalanceSheetQuery = () => {
setLocationQuery,
};
};
/**
* Retrieves the trial balance sheet http query.
* @returns {object}
*/
export const useTrialBalanceSheetHttpQuery = () => {
const { query } = useTrialBalanceSheetQuery();
return React.useMemo(() => transformFilterFormToQuery(query), [query]);
};

View File

@@ -19,6 +19,7 @@ import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions
import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
import { saveInvoke, compose } from '@/utils';
import { VendorSummarySheetExportMenu } from './components';
/**
* Vendors balance summary action bar.
@@ -106,11 +107,18 @@ function VendorsBalanceSummaryActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<VendorSummarySheetExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -31,7 +31,7 @@ export default function VendorsBalanceSummaryTable({
>
<VendorBalanceDataTable
columns={columns}
data={table.data}
data={table.rows}
rowClassNames={tableRowTypesToClassnames}
noInitialFetch={true}
sticky={true}

View File

@@ -1,13 +1,18 @@
// @ts-nocheck
import React from 'react';
import React, { useRef } from 'react';
import intl from 'react-intl-universal';
import * as R from 'ramda';
import classNames from 'classnames';
import { If } from '@/components';
import { Align } from '@/constants';
import { AppToaster, If, Stack } from '@/components';
import { Align, CLASSES } from '@/constants';
import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { Intent, Menu, MenuItem, ProgressBar, Text } from '@blueprintjs/core';
import {
useVendorBalanceSummaryCsvExport,
useVendorBalanceSummaryXlsxExport,
} from '@/hooks/query';
/**
* Retrieve vendors balance summary columns.
@@ -85,3 +90,86 @@ export function VendorsSummarySheetLoadingBar() {
</If>
);
}
/**
* Vendor summary sheet export menu.
* @returns {JSX.Element}
*/
export function VendorSummarySheetExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[CLASSES.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useVendorBalanceSummaryXlsxExport({
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useVendorBalanceSummaryCsvExport({
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport().then(() => {});
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport().then(() => {});
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -19,6 +19,7 @@ import withVendorsTransaction from './withVendorsTransaction';
import withVendorsTransactionsActions from './withVendorsTransactionsActions';
import { compose, saveInvoke } from '@/utils';
import { VendorTransactionsExportMenu } from './components';
/**
* vendors transactions actions bar.
@@ -114,11 +115,18 @@ function VendorsTransactionsActionsBar({
icon={<Icon icon="print-16" iconSize={16} />}
text={<T id={'print'} />}
/>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
<Popover
content={<VendorTransactionsExportMenu />}
interactionKind={PopoverInteractionKind.CLICK}
placement="bottom-start"
minimal
>
<Button
className={Classes.MINIMAL}
icon={<Icon icon="file-export-16" iconSize={16} />}
text={<T id={'export'} />}
/>
</Popover>
</NavbarGroup>
</DashboardActionsBar>
);

View File

@@ -1,11 +1,24 @@
// @ts-nocheck
import React from 'react';
import React, { useRef } from 'react';
import intl from 'react-intl-universal';
import {
Classes,
Intent,
Menu,
MenuItem,
ProgressBar,
Text,
} from '@blueprintjs/core';
import classNames from 'classnames';
import { If } from '@/components';
import { AppToaster, If, Stack } from '@/components';
import { useVendorsTransactionsContext } from './VendorsTransactionsProvider';
import FinancialLoadingBar from '../FinancialLoadingBar';
import { getColumnWidth } from '@/utils';
import {
useVendorsTransactionsCsvExport,
useVendorsTransactionsXlsxExport,
} from '@/hooks/query';
/**
* Retrieve vendors transactions columns.
@@ -77,7 +90,7 @@ export const useVendorsTransactionsColumns = () => {
};
/**
* vendors transactions loading bar.
* Vendors transactions loading bar.
*/
export function VendorsTransactionsLoadingBar() {
const { isVendorsTransactionFetching } = useVendorsTransactionsContext();
@@ -88,3 +101,86 @@ export function VendorsTransactionsLoadingBar() {
</If>
);
}
/**
* Vendor transactions export menu.
*/
export function VendorTransactionsExportMenu() {
const toastKey = useRef(null);
const commonToastConfig = {
isCloseButtonShown: true,
timeout: 2000,
};
const { query } = useVendorsTransactionsContext();
const openProgressToast = (amount: number) => {
return (
<Stack spacing={8}>
<Text>The report has been exported successfully.</Text>
<ProgressBar
className={classNames('toast-progress', {
[Classes.PROGRESS_NO_STRIPES]: amount >= 100,
})}
intent={amount < 100 ? Intent.PRIMARY : Intent.SUCCESS}
value={amount / 100}
/>
</Stack>
);
};
// Export the report to xlsx.
const { mutateAsync: xlsxExport } = useVendorsTransactionsXlsxExport(query, {
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Export the report to csv.
const { mutateAsync: csvExport } = useVendorsTransactionsCsvExport({
onDownloadProgress: (xlsxExportProgress: number) => {
if (!toastKey.current) {
toastKey.current = AppToaster.show({
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
});
} else {
AppToaster.show(
{
message: openProgressToast(xlsxExportProgress),
...commonToastConfig,
},
toastKey.current,
);
}
},
});
// Handle csv export button click.
const handleCsvExportBtnClick = () => {
csvExport();
};
// Handle xlsx export button click.
const handleXlsxExportBtnClick = () => {
xlsxExport();
};
return (
<Menu>
<MenuItem
text={'XLSX (Microsoft Excel)'}
onClick={handleXlsxExportBtnClick}
/>
<MenuItem text={'CSV'} onClick={handleCsvExportBtnClick} />
</Menu>
);
}

View File

@@ -1,16 +1,14 @@
// @ts-nocheck
import { useRequestQuery } from '../useQueryRequest';
import {
trialBalanceSheetReducer,
generalLedgerTableRowsReducer,
journalTableRowsReducer,
ARAgingSummaryTableRowsMapper,
APAgingSummaryTableRowsMapper,
inventoryValuationReducer,
purchasesByItemsReducer,
salesByItemsReducer,
} from '@/containers/FinancialStatements/reducers';
import t from './types';
import { useDownloadFile } from '../useDownloadFile';
/**
* Retrieve balance sheet.
@@ -33,6 +31,34 @@ export function useBalanceSheet(query, props) {
);
}
export const useBalanceSheetXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/balance_sheet',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'balance_sheet.xlsx',
...args,
});
};
export const useBalanceSheetCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/balance_sheet',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'balance_sheet.csv',
...args,
});
};
/**
* Retrieve trial balance sheet.
*/
@@ -54,6 +80,34 @@ export function useTrialBalanceSheet(query, props) {
);
}
export const useTrialBalanceSheetXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/trial_balance_sheet',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'trial_balance_sheet.xlsx',
...args,
});
};
export const useTrialBalanceSheetCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/trial_balance_sheet',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'trial_balance_sheet.csv',
...args,
});
};
/**
* Retrieve profit/loss (P&L) sheet.
*/
@@ -75,6 +129,34 @@ export function useProfitLossSheet(query, props) {
);
}
export const useProfitLossSheetXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/profit_loss_sheet',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'profit_loss_sheet.xlsx',
...args,
});
};
export const useProfitLossSheetCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/profit_loss_sheet',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'profit_loss_sheet.csv',
...args,
});
};
/**
* Retrieve general ledger (GL) sheet.
*/
@@ -144,6 +226,34 @@ export function useARAgingSummaryReport(query, props) {
);
}
export const useARAgingSheetXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/receivable_aging_summary',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'receivable_aging_summary.xlsx',
...args,
});
};
export const useARAgingSheetCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/receivable_aging_summary',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'receivable_aging_summary.csv',
...args,
});
};
/**
* Retrieve A/P aging summary report.
*/
@@ -165,6 +275,34 @@ export function useAPAgingSummaryReport(query, props) {
);
}
export const useAPAgingSheetXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/payable_aging_summary',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'payable_aging_summary.xlsx',
...args,
});
};
export const useAPAgingSheetCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/payable_aging_summary',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'payable_aging_summary.csv',
...args,
});
};
/**
* Retrieve inventory valuation.
*/
@@ -270,6 +408,34 @@ export function useCustomerBalanceSummaryReport(query, props) {
);
}
export const useCustomerBalanceSummaryXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/customer-balance-summary',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'customer_balance_summary.xlsx',
...args,
});
};
export const useCustomerBalanceSummaryCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/customer-balance-summary',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'customer_balance_summary.csv',
...args,
});
};
/**
* Retrieve vendors balance summary report.
*/
@@ -299,6 +465,36 @@ export function useVendorsBalanceSummaryReport(query, props) {
);
}
export const useVendorBalanceSummaryXlsxExport = (args) => {
const url = '/financial_statements/vendor-balance-summary';
const config = {
headers: {
accept: 'application/xlsx',
},
};
const filename = 'vendor_balance_summary.xlsx';
return useDownloadFile({
url,
config,
filename,
...args,
});
};
export const useVendorBalanceSummaryCsvExport = (args) => {
return useDownloadFile({
url: '/financial_statements/vendor-balance-summary',
config: {
headers: {
accept: 'application/csv',
},
},
filename: 'vendor_balance_summary.csv',
...args,
});
};
/**
* Retrieve customers transactions report.
*/
@@ -327,6 +523,38 @@ export function useCustomersTransactionsReport(query, props) {
);
}
export const useCustomersTransactionsXlsxExport = (query, args) => {
const url = '/financial_statements/transactions-by-customers';
const config = {
headers: {
accept: 'application/xlsx',
},
params: query,
};
const filename = 'customers_transactions.xlsx';
return useDownloadFile({
url,
config,
filename,
...args,
});
};
export const useCustomersTransactionsCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/transactions-by-customers',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'customers_transactions.csv',
...args,
});
};
/**
* Retrieve vendors transactions report.
*/
@@ -344,7 +572,7 @@ export function useVendorsTransactionsReport(query, props) {
{
select: (res) => ({
data: res.data.table,
tableRows: res.data.table.data,
tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
@@ -355,6 +583,38 @@ export function useVendorsTransactionsReport(query, props) {
);
}
export const useVendorsTransactionsXlsxExport = (query, args) => {
const url = '/financial_statements/transactions-by-vendors';
const config = {
headers: {
accept: 'application/xlsx',
},
params: query,
};
const filename = 'transactions_by_vendor.xlsx';
return useDownloadFile({
url,
config,
filename,
...args,
});
};
export const useVendorsTransactionsCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/transactions-by-vendors',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'transactions_by_vendor.csv',
...args,
});
};
/**
* Retrieve cash flow statement report.
*/
@@ -374,7 +634,7 @@ export function useCashFlowStatementReport(query, props) {
columns: res.data.table.columns,
query: res.data.query,
meta: res.data.meta,
tableRows: res.data.table.data,
tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
@@ -387,6 +647,42 @@ export function useCashFlowStatementReport(query, props) {
);
}
export const useCashFlowStatementXlsxExport = (query, args) => {
const url = '/financial_statements/cash-flow';
const config = {
headers: {
accept: 'application/xlsx',
},
params: query,
};
const filename = 'cashflow_statement.xlsx';
return useDownloadFile({
url,
config,
filename,
...args,
});
};
export const useCashFlowStatementCsvExport = (query, args) => {
const url = '/financial_statements/cash-flow';
const config = {
headers: {
accept: 'application/csv',
},
params: query,
};
const filename = 'cashflow_statement.csv';
return useDownloadFile({
url,
config,
filename,
...args,
});
};
/**
* Retrieve inventory item detail report.
*/
@@ -406,7 +702,7 @@ export function useInventoryItemDetailsReport(query, props) {
columns: res.data.table.columns,
query: res.data.query,
meta: res.data.meta,
tableRows: res.data.table.data,
tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
@@ -419,6 +715,34 @@ export function useInventoryItemDetailsReport(query, props) {
);
}
export const useInventoryItemDetailsXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/inventory-item-details',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'inventory_item_details.xlsx',
...args,
});
};
export const useInventoryItemDetailsCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/inventory-item-details',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'inventory_item_details.csv',
...args,
});
};
/**
* Retrieve transactions by reference report.
*/
@@ -460,3 +784,31 @@ export function useSalesTaxLiabilitySummary(query, props) {
},
);
}
export const useSalesTaxLiabilitySummaryXlsxExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/sales-tax-liability-summary',
config: {
headers: {
accept: 'application/xlsx',
},
params: query,
},
filename: 'sales_tax_liability_summary.xlsx',
...args,
});
};
export const useSalesTaxLiabilitySummaryCsvExport = (query, args) => {
return useDownloadFile({
url: '/financial_statements/sales-tax-liability-summary',
config: {
headers: {
accept: 'application/csv',
},
params: query,
},
filename: 'sales_tax_liability_summary.csv',
...args,
});
};

View File

@@ -0,0 +1,72 @@
// @ts-nocheck
import axios, { AxiosError, AxiosRequestConfig } from 'axios';
import { useState } from 'react';
import { useMutation } from 'react-query';
import useApiRequest from './useRequest';
interface IArgs {
url: string;
filename: string;
mime?: string;
config?: AxiosRequestConfig;
onDownloadProgress?: (progress: number) => void;
}
export const useDownloadFile = (args: IArgs) => {
const apiRequest = useApiRequest();
const mutation = useMutation<void, AxiosError, IArgs>(() =>
apiRequest
.get(args.url, {
responseType: 'blob',
onDownloadProgress: (ev) => {
args.onDownloadProgress &&
args.onDownloadProgress(Math.round((ev.loaded * 100) / ev.total));
},
...args.config,
})
.then((res) => {
downloadFile(res.data, args.filename, args.mime);
return res;
}),
);
return { ...mutation };
};
export function downloadFile(data, filename, mime, bom) {
var blobData = typeof bom !== 'undefined' ? [bom, data] : [data];
var blob = new Blob(blobData, { type: mime || 'application/octet-stream' });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were
// revoked by closing the blob for which they were created.
// These URLs will no longer resolve as the data backing
// the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var blobURL =
window.URL && window.URL.createObjectURL
? window.URL.createObjectURL(blob)
: window.webkitURL.createObjectURL(blob);
var tempLink = document.createElement('a');
tempLink.style.display = 'none';
tempLink.href = blobURL;
tempLink.setAttribute('download', filename);
// Safari thinks _blank anchor are pop ups. We only want to set _blank
// target if the browser does not support the HTML5 download attribute.
// This allows you to download files in desktop safari if pop up blocking
// is enabled.
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank');
}
document.body.appendChild(tempLink);
tempLink.click();
// Fixes "webkit blob resource error 1"
setTimeout(function () {
document.body.removeChild(tempLink);
window.URL.revokeObjectURL(blobURL);
}, 200);
}
}