Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feature) Export to PDF for ledgers and tax reports #775

Merged
merged 27 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
640f4a9
Merge pull request #770 from bitfinexcom/staging
prdn Feb 14, 2024
5dcc1dd
Add is pdf requred const
alexstotsky Feb 8, 2024
0851da8
Implement export to pdf status setter
alexstotsky Feb 8, 2024
bd4b4df
Actualize query reducers handling cases, update init state
alexstotsky Feb 8, 2024
f39defb
Actualize movements entries props shape
alexstotsky Feb 8, 2024
bed77c9
Add getIsPdfExportRequired selector
alexstotsky Feb 8, 2024
3174237
Implement isTaxReport checker
alexstotsky Feb 8, 2024
15bf527
Actualize export keys/descriptions
alexstotsky Feb 8, 2024
87b114e
Unify export dialog title
alexstotsky Feb 8, 2024
120c41d
Actualize local status description
alexstotsky Feb 8, 2024
2bcdb5c
Actualize query sagas flow for tax report exporting case
alexstotsky Feb 9, 2024
e5c8aca
[wip]Export to pdf switcher
alexstotsky Feb 9, 2024
5ee5891
Cleanup
alexstotsky Feb 9, 2024
6136fef
Adjust pdf switcher positioning
alexstotsky Feb 9, 2024
c8c69b7
Implement swicthing pdf flow
alexstotsky Feb 9, 2024
a29ce40
Actualize export, cleanup
alexstotsky Feb 9, 2024
b53095d
Optimize pdf export switcher
alexstotsky Feb 9, 2024
c6f1c4c
Actualize export methods names
alexstotsky Feb 12, 2024
71c1b6f
Lint fix
alexstotsky Feb 12, 2024
61142ed
Implement export dialog helpers
alexstotsky Feb 13, 2024
c1b5c4b
Enhance pdf switcher availability checking flow
alexstotsky Feb 13, 2024
4aecc17
Improve getShowPdfSwitcher checking flow
alexstotsky Feb 13, 2024
6a800eb
Actualize ledgers get export method
alexstotsky Feb 13, 2024
0cbbd15
Update getOptions saga config for ledgers case
alexstotsky Feb 13, 2024
9e988cc
Actualize result prop-types, improve linting
alexstotsky Feb 19, 2024
dface5e
Cleanup
alexstotsky Feb 19, 2024
a71ab06
Lint fix
alexstotsky Feb 19, 2024
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
7 changes: 4 additions & 3 deletions public/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@
},
"download": {
"query": "Prepare Export",
"title": "Export CSV",
"title": "Export",
"prepare": "Bitfinex will prepare your data during",
"send": "and send to {{email}}.",
"store": "and store to your local folder.",
Expand All @@ -283,11 +283,12 @@
"okay": "Okay",
"remoteStorage": "Remote storage",
"status": {
"local": "Export csv generated, files are saved in: ",
"local": "Export generated, files are saved in: ",
"email": "Generating your CSV report, we'll send it to you via email as soon as it's ready..."
},
"success": "Success",
"targets": "Data to Export"
"targets": "Data to Export",
"exportAsPdf": "Export as PDF"
},
"fcredit": {
"title": "Funding Credits (Used)",
Expand Down
13 changes: 13 additions & 0 deletions src/components/ExportDialog/ExportDialog.helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import config from 'config'
import queryConstants from 'state/query/constants'

const { showFrameworkMode } = config

const EXPORT_TO_PDF_WHITELIST = [
queryConstants.MENU_LEDGERS,
queryConstants.MENU_TAX_REPORT,
]

export const getShowPdfSwitcher = (targets) => (
showFrameworkMode && EXPORT_TO_PDF_WHITELIST.some(target => targets.includes(target))
)
15 changes: 13 additions & 2 deletions src/components/ExportDialog/ExportDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import config from 'config'
import { tracker } from 'utils/trackers'
import { formatDate } from 'state/utils'
import { getTarget } from 'state/query/utils'
import ExportToPdf from 'ui/ExportToPdf'
import ShowMilliseconds from 'ui/ShowMilliseconds'
import queryConstants from 'state/query/constants'
import DateFormatSelector from 'ui/DateFormatSelector'

import { getShowPdfSwitcher } from './ExportDialog.helpers'
import ExportTargetsSelector from './ExportDialog.TargetsSelector'

const { showFrameworkMode } = config
Expand Down Expand Up @@ -123,6 +125,7 @@ class ExportDialog extends PureComponent {
if (!isOpen) {
return null
}
const showPdfSwitcher = getShowPdfSwitcher(currentTargets)
const showLoader = showFrameworkMode && isExporting
const target = getTarget(location.pathname)
const isWallets = location && location.pathname && target === queryConstants.MENU_WALLETS
Expand Down Expand Up @@ -182,8 +185,16 @@ class ExportDialog extends PureComponent {
</div>
</div>
<div className='export-dialog-row'>
<span>{t('preferences.milliseconds')}</span>
<ShowMilliseconds />
{showPdfSwitcher && (
<div className='export-dialog-item'>
<span>{t('download.exportAsPdf')}</span>
<ExportToPdf />
</div>
)}
<div className='export-dialog-item'>
<span>{t('preferences.milliseconds')}</span>
<ShowMilliseconds />
</div>
</div>
</div>
<div className={Classes.DIALOG_FOOTER}>
Expand Down
68 changes: 66 additions & 2 deletions src/components/TaxReport/Result/Result.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import _isNumber from 'lodash/isNumber'

import NoData from 'ui/NoData'
Expand All @@ -10,7 +11,6 @@ import { checkFetch, checkInit } from 'state/utils'
import { getFrameworkPositionsColumns } from 'utils/columns'
import getMovementsColumns from 'components/Movements/Movements.columns'

import { propTypes } from './Result.props'
import getBalancesColumns from './Balances.columns'
import TAX_REPORT_SECTIONS from '../TaxReport.sections'

Expand Down Expand Up @@ -218,6 +218,70 @@ class Result extends PureComponent {
}
}

Result.propTypes = propTypes
Result.propTypes = {
data: PropTypes.shape({
startingPositionsSnapshot: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.number,
basePrice: PropTypes.number,
liquidationPrice: PropTypes.number,
marginFunding: PropTypes.number,
marginFundingType: PropTypes.number,
mtsUpdate: PropTypes.number,
pair: PropTypes.string.isRequired,
pl: PropTypes.number,
plPerc: PropTypes.number,
}),
).isRequired,
endingPositionsSnapshot: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.number,
basePrice: PropTypes.number,
liquidationPrice: PropTypes.number,
marginFunding: PropTypes.number,
marginFundingType: PropTypes.number,
mtsUpdate: PropTypes.number,
pair: PropTypes.string.isRequired,
pl: PropTypes.number,
plPerc: PropTypes.number,
}),
).isRequired,
finalState: PropTypes.shape({
startingPeriodBalances: PropTypes.shape({
walletsTotalBalanceUsd: PropTypes.number,
positionsTotalPlUsd: PropTypes.number,
totalResult: PropTypes.number,
}),
movements: PropTypes.arrayOf(PropTypes.shape({
amount: PropTypes.number,
amountUsd: PropTypes.number,
currency: PropTypes.string,
currencyName: PropTypes.string,
destinationAddress: PropTypes.string,
fees: PropTypes.number,
id: PropTypes.number,
mtsStarted: PropTypes.number,
mtsUpdated: PropTypes.number,
note: PropTypes.string,
status: PropTypes.string,
subUserId: PropTypes.number,
transactionId: PropTypes.string,
})).isRequired,
movementsTotalAmount: PropTypes.number,
endingPeriodBalances: PropTypes.shape({
walletsTotalBalanceUsd: PropTypes.number,
positionsTotalPlUsd: PropTypes.number,
totalResult: PropTypes.number,
}),
totalResult: PropTypes.number,
}).isRequired,
}).isRequired,
pageLoading: PropTypes.bool.isRequired,
dataReceived: PropTypes.bool.isRequired,
getFullTime: PropTypes.func.isRequired,
timeOffset: PropTypes.string.isRequired,
refresh: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
}

export default Result
53 changes: 0 additions & 53 deletions src/components/TaxReport/Result/Result.props.js

This file was deleted.

8 changes: 8 additions & 0 deletions src/state/query/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,19 @@ export function setIsCsvExporting(isExporting) {
}
}

export function setIsPdfRequired(isPdfRequired) {
return {
type: types.SET_IS_PDF_REQUIRED,
payload: isPdfRequired,
}
}

export default {
exportCsv,
setRemoteUrn,
prepareExport,
setExportEmail,
setIsPdfRequired,
setIsCsvExporting,
setLocalExportPath,
}
1 change: 1 addition & 0 deletions src/state/query/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export default {
SET_LOCAL_EXPORT_PATH: 'BITFINEX/EXPORT/CSV_FOLDER_PATH',
SET_REMOTE_CSV_URN: 'BITFINEX/EXPORT/CSV_REMOTE_URN',
SET_IS_CSV_EXPORTING: 'BITFINEX/EXPORT/IS_CSV_EXPORTING',
SET_IS_PDF_REQUIRED: 'BITFINEX/EXPORT/IS_PDF_REQUIRED',
PREPARE_EXPORT: 'BITFINEX/EXPORT/PREPARE',
SET_EXPORT_EMAIL: 'BITFINEX/EMAIL/EXPORT',
FILTER_ID: 'id',
Expand Down
6 changes: 6 additions & 0 deletions src/state/query/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const initialState = {
localExportPath: null,
remoteUrn: null,
isCsvExporting: false,
isPDFRequired: true,
}

export function queryReducer(state = initialState, action) {
Expand All @@ -32,6 +33,11 @@ export function queryReducer(state = initialState, action) {
...state,
isCsvExporting: payload,
}
case types.SET_IS_PDF_REQUIRED:
return {
...state,
isPDFRequired: payload,
}
case authTypes.LOGOUT:
return initialState
default:
Expand Down
12 changes: 8 additions & 4 deletions src/state/query/saga.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ import config from 'config'

import actions from './actions'
import types from './constants'
import { getExportEmail } from './selectors'
import { getExportEmail, getIsPdfExportRequired } from './selectors'
import {
getQueryLimit,
NO_TIME_FRAME_TARGETS,
Expand Down Expand Up @@ -129,7 +129,7 @@ const {
}
*/

const getMultipleCsv = params => makeFetchCall('getMultipleCsv', params)
const getMultipleCsv = params => makeFetchCall('getMultipleFile', params)

function getSelector(target) {
switch (target) {
Expand Down Expand Up @@ -250,6 +250,7 @@ function* getOptions({ target }) {
const isVSPrevDayBalance = showFrameworkMode ? yield select(getIsVSPrevDayBalance) : ''
const isUnrealizedProfitExcluded = showFrameworkMode ? yield select(getIsUnrealizedProfitExcluded) : ''
const isVsAccountBalanceSelected = showFrameworkMode ? yield select(getIsVsAccountBalanceSelected) : ''
const isPdfExportRequired = showFrameworkMode ? yield select(getIsPdfExportRequired) : false

switch (target) {
case MENU_ACCOUNT_BALANCE:
Expand Down Expand Up @@ -288,6 +289,8 @@ function* getOptions({ target }) {
options.symbol = formatSymbol(target, sign.targetSymbols)
break
case MENU_TAX_REPORT:
options.isPDFRequired = isPdfExportRequired
break
case MENU_LOGINS:
case MENU_CHANGE_LOGS:
break
Expand Down Expand Up @@ -338,7 +341,8 @@ function* getOptions({ target }) {
options.method = 'getPayInvoiceListCsv'
break
case MENU_LEDGERS:
options.method = 'getLedgersCsv'
options.method = 'getLedgersFile'
options.isPDFRequired = isPdfExportRequired
options.category = yield select(getLedgersCategory)
break
case MENU_LOAN_REPORT:
Expand Down Expand Up @@ -385,7 +389,7 @@ function* getOptions({ target }) {
options.method = 'getFullSnapshotReportCsv'
break
case MENU_TAX_REPORT:
options.method = 'getFullTaxReportCsv'
options.method = 'getFullTaxReportFile'
break
case MENU_TRADED_VOLUME:
options.method = 'getTradedVolumeCsv'
Expand Down
2 changes: 2 additions & 0 deletions src/state/query/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ export const getRemoteUrn = state => getQuery(state).remoteUrn
export const getExportEmail = state => getQuery(state).exportEmail
export const getLocalExportPath = state => getQuery(state).localExportPath
export const getIsCsvExporting = state => getQuery(state)?.isCsvExporting ?? false
export const getIsPdfExportRequired = state => getQuery(state)?.isPDFRequired ?? false

export default {
getQuery,
getRemoteUrn,
getExportEmail,
getIsCsvExporting,
getLocalExportPath,
getIsPdfExportRequired,
}
27 changes: 27 additions & 0 deletions src/ui/ExportToPdf/ExportToPdf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Checkbox } from '@blueprintjs/core'

import { tracker } from 'utils/trackers'
import { setIsPdfRequired } from 'state/query/actions'
import { getIsPdfExportRequired } from 'state/query/selectors'

const ExportToPdf = () => {
const dispatch = useDispatch()
const isPdfExportRequired = useSelector(getIsPdfExportRequired)

const handleChange = useCallback(() => {
tracker.trackEvent('Export as PDF')
dispatch(setIsPdfRequired(!isPdfExportRequired))
}, [dispatch, tracker, isPdfExportRequired])

return (
<Checkbox
large
onChange={handleChange}
checked={isPdfExportRequired}
/>
)
}

export default ExportToPdf
1 change: 1 addition & 0 deletions src/ui/ExportToPdf/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ExportToPdf'