diff --git a/client/package.json b/client/package.json index 976cf75fa..15ac6d124 100644 --- a/client/package.json +++ b/client/package.json @@ -30,6 +30,7 @@ "case-sensitive-paths-webpack-plugin": "2.3.0", "cross-env": "^7.0.2", "css-loader": "3.4.2", + "deep-map-keys": "^2.0.1", "dotenv": "8.2.0", "dotenv-expand": "5.1.0", "eslint": "^6.6.0", diff --git a/client/src/common/numberFormatsOptions.js b/client/src/common/numberFormatsOptions.js index d39845288..0315eae93 100644 --- a/client/src/common/numberFormatsOptions.js +++ b/client/src/common/numberFormatsOptions.js @@ -1,18 +1,19 @@ export const moneyFormat = [ - { id: 'total', text: 'Total rows' }, - { id: 'always', text: 'Always' }, - { id: 'none', text: 'None' }, + { key: 'total', text: 'Total rows' }, + { key: 'always', text: 'Always' }, + { key: 'none', text: 'None' }, ]; export const negativeFormat = [ - { id: 'parentheses', text: 'Parentheses ($1000)' }, - { id: 'mines', text: 'Minus -$1000' }, + { key: 'parentheses', text: '($1000)' }, + { key: 'mines', text: '-$1000' }, ]; export const decimalPlaces = [ - { text: '1 Decimals', label: '$0.1', id: 1 }, - { text: '2 Decimals', label: '$0.01', id: 2 }, - { text: '3 Decimals', label: '$0.001', id: 3 }, - { text: '4 Decimals', label: '$0.0001', id: 4 }, - { text: '5 Decimals', label: '$0.00001', id: 5 }, + { text: '$1', key: 0 }, + { text: '$0.1', key: 1 }, + { text: '$0.01', key: 2 }, + { text: '$0.001', key: 3 }, + { text: '$0.0001', key: 4 }, + { text: '$0.00001', key: 5 }, ]; diff --git a/client/src/components/FinancialSheet.js b/client/src/components/FinancialSheet.js index a387d6c3d..a46eafdf6 100644 --- a/client/src/components/FinancialSheet.js +++ b/client/src/components/FinancialSheet.js @@ -1,9 +1,11 @@ import React, { useMemo, useCallback } from 'react'; import moment from 'moment'; import classnames from 'classnames'; -import { LoadingIndicator, MODIFIER } from 'components'; import { FormattedMessage as T, useIntl } from 'react-intl'; -import { If } from 'components'; + +import { If, LoadingIndicator, MODIFIER } from 'components'; + +import 'style/pages/FinancialStatements/FinancialSheet.scss'; export default function FinancialSheet({ companyName, diff --git a/client/src/components/NumberFormatDropdown/NumberFormatFields.js b/client/src/components/NumberFormatDropdown/NumberFormatFields.js new file mode 100644 index 000000000..169a5a5e9 --- /dev/null +++ b/client/src/components/NumberFormatDropdown/NumberFormatFields.js @@ -0,0 +1,139 @@ +import React from 'react'; +import { FastField, ErrorMessage } from 'formik'; +import { FormGroup, Checkbox, Switch } from '@blueprintjs/core'; +import { CLASSES } from 'common/classes'; +import { ListSelect } from 'components'; +import { FormattedMessage as T } from 'react-intl'; +import { inputIntent } from 'utils'; +import { + moneyFormat, + negativeFormat, + decimalPlaces, +} from 'common/numberFormatsOptions'; +import classNames from 'classnames'; + +/** + * Number Formats Fields. + */ +export default function NumberFormatFields({}) { + return ( +
+ {/*------------ Negative formats -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL)} + > + { + form.setFieldValue('negativeFormat', format.key); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'key'} + textProp={'text'} + popoverProps={{ minimal: true, captureDismiss: true }} + /> + + )} + + + {/*------------ Decimal places -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL)} + > + { + form.setFieldValue('precision', format.key); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'key'} + textProp={'text'} + popoverProps={{ minimal: true, captureDismiss: true }} + /> + + )} + + + {/*------------ Money formats -----------*/} + + {({ form, field: { value }, meta: { error, touched } }) => ( + } + helperText={} + intent={inputIntent({ error, touched })} + className={classNames(CLASSES.FILL)} + > + { + form.setFieldValue('formatMoney', format.key); + }} + filterable={false} + selectedItem={value} + selectedItemProp={'key'} + textProp={'text'} + popoverProps={{ minimal: true, captureDismiss: true }} + /> + + )} + + +
+ {/*------------ show zero -----------*/} + + {({ field }) => ( + + } + name={'showZero'} + {...field} + /> + + )} + + + {/*------------ show negative in red-----------*/} + + {({ field }) => ( + + } + name={'showInRed'} + {...field} + /> + + )} + + + {/*------------ Divide on 1000 -----------*/} + + {({ field }) => ( + + } + name={'divideOn1000'} + {...field} + /> + + )} + +
+
+ ); +} diff --git a/client/src/components/NumberFormatDropdown/NumberFormatFooter.js b/client/src/components/NumberFormatDropdown/NumberFormatFooter.js new file mode 100644 index 000000000..bb42b0ca9 --- /dev/null +++ b/client/src/components/NumberFormatDropdown/NumberFormatFooter.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { useFormikContext } from 'formik'; +import { Button, Classes, Intent } from '@blueprintjs/core'; +import classNames from 'classnames'; +import { FormattedMessage as T } from 'react-intl'; + +/** + * Number format footer. + */ +export default function NumberFormatFooter({ + // #ownProps + onCancelClick, + submitDisabled +}) { + return ( +
+ + + +
+ ); +} diff --git a/client/src/components/NumberFormats/NumberFormats.schema.js b/client/src/components/NumberFormatDropdown/NumberFormats.schema.js similarity index 100% rename from client/src/components/NumberFormats/NumberFormats.schema.js rename to client/src/components/NumberFormatDropdown/NumberFormats.schema.js diff --git a/client/src/components/NumberFormatDropdown/index.js b/client/src/components/NumberFormatDropdown/index.js new file mode 100644 index 000000000..263fa79f2 --- /dev/null +++ b/client/src/components/NumberFormatDropdown/index.js @@ -0,0 +1,45 @@ +import React, { useCallback } from 'react'; +import { Formik, Form } from 'formik'; + +import 'style/pages/FinancialStatements/NumberFormatDropdown.scss'; + +import NumberFormatFields from './NumberFormatFields'; +import NumberFormatFooter from './NumberFormatFooter'; + +/** + * Number format form popover content. + */ +export default function NumberFormatDropdown({ + numberFormat = {}, + onSubmit, + submitDisabled = false, +}) { + const initialValues = { + formatMoney: 'total', + showZero: false, + showInRed: false, + divideOn1000: false, + negativeFormat: 'mines', + precision: 2, + ...numberFormat + }; + // Handle cancel button click. + const handleCancelClick = useCallback(() => {}, []); + + // Handle form submit. + const handleFormSubmit = (values, { setSubmitting }) => { + setSubmitting(true); + onSubmit(values); + }; + + return ( +
+ +
+ + + +
+
+ ); +} diff --git a/client/src/components/NumberFormats/NumberFormatFields.js b/client/src/components/NumberFormats/NumberFormatFields.js deleted file mode 100644 index c2a41fea1..000000000 --- a/client/src/components/NumberFormats/NumberFormatFields.js +++ /dev/null @@ -1,169 +0,0 @@ -import React from 'react'; -import { Form, FastField, ErrorMessage, useFormikContext } from 'formik'; -import { - Button, - Classes, - FormGroup, - InputGroup, - Intent, - Checkbox, -} from '@blueprintjs/core'; -import { CLASSES } from 'common/classes'; -import { Row, Col, ListSelect } from 'components'; -import { FormattedMessage as T, useIntl } from 'react-intl'; -import { inputIntent } from 'utils'; -import { - moneyFormat, - negativeFormat, - decimalPlaces, -} from 'common/numberFormatsOptions'; -import classNames from 'classnames'; - -/** - * Number Formats Fields. - */ -export default function NumberFormatFields({ - // #ownProps - onCancelClick, -}) { - const { isSubmitting } = useFormikContext(); - return ( -
-
- {/*------------ Money formats -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - helperText={} - intent={inputIntent({ error, touched })} - className={classNames(CLASSES.FILL)} - > - { - form.setFieldValue('format_money', format.name); - }} - filterable={false} - selectedItem={value} - selectedItemProp={'id'} - textProp={'text'} - popoverProps={{ minimal: true, captureDismiss: true }} - /> - - )} - - {/*------------ Negative formats -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - helperText={} - intent={inputIntent({ error, touched })} - className={classNames(CLASSES.FILL)} - > - { - form.setFieldValue('negative_format', format.name); - }} - filterable={false} - selectedItem={value} - selectedItemProp={'id'} - textProp={'text'} - popoverProps={{ minimal: true, captureDismiss: true }} - /> - - )} - - - {/*------------ Decimal places -----------*/} - - {({ form, field: { value }, meta: { error, touched } }) => ( - } - helperText={} - intent={inputIntent({ error, touched })} - className={classNames(CLASSES.FILL)} - > - { - form.setFieldValue('precision', format.key); - }} - filterable={false} - selectedItem={value} - selectedItemProp={'id'} - labelProp={'label'} - textProp={'text'} - popoverProps={{ minimal: true, captureDismiss: true }} - /> - - )} - - - {/*------------ show zero -----------*/} - - {({ field }) => ( - - } - name={'show_zero'} - {...field} - /> - - )} - - {/*------------ show negative in red-----------*/} - - {({ field }) => ( - - } - name={'show_in_red'} - {...field} - /> - - )} - - {/*------------ Divide on 1000 -----------*/} - - {({ field }) => ( - - } - name={'divide_on_1000'} - {...field} - /> - - )} - -
-
- - - -
-
- ); -} diff --git a/client/src/components/NumberFormats/index.js b/client/src/components/NumberFormats/index.js deleted file mode 100644 index 1d1a5a87a..000000000 --- a/client/src/components/NumberFormats/index.js +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useState, useCallback, useMemo } from 'react'; -import { Classes } from '@blueprintjs/core'; -import { Formik } from 'formik'; -import classNames from 'classnames'; -import NumberFormatFields from './NumberFormatFields'; - -import { compose } from 'utils'; - -/** - * Number format form popover content. - */ -function NumberFormats() { - const initialValues = useMemo( - () => ({ - format_money: '', - show_zero: '', - show_in_red: '', - divide_on_1000: '', - negative_format: '', - precision: '', - }), - [], - ); - // Handle cancel button click. - const handleCancelClick = useCallback(() => {}, []); - - // Handle form submit. - const handleFormSubmit = (values, { setSubmitting }) => { - setSubmitting(true); - const form = { ...values }; - }; - - return ( -
- - - -
- ); -} - -export default NumberFormats; diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js index 6b26c8e29..54faeefe9 100644 --- a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js +++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.js @@ -94,9 +94,19 @@ function ReceivableAgingSummarySheet({ [refreshARAgingSummary, toggleFilterARAgingSummary], ); + const handleNumberFormatSubmit = (numberFormat) => { + setQuery({ + ...query, + numberFormat + }); + refreshARAgingSummary(true); + }; + return ( - + diff --git a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js index cd826052c..9059987cc 100644 --- a/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js +++ b/client/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryActionsBar.js @@ -13,11 +13,13 @@ import classNames from 'classnames'; import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar'; import Icon from 'components/Icon'; +import NumberFormatDropdown from 'components/NumberFormatDropdown'; import withARAgingSummary from './withARAgingSummary'; import withARAgingSummaryActions from './withARAgingSummaryActions'; import { compose } from 'utils'; +import { safeInvoke } from '@blueprintjs/core/lib/esm/common/utils'; /** * AR Aging summary sheet - Actions bar. @@ -25,10 +27,15 @@ import { compose } from 'utils'; function ARAgingSummaryActionsBar({ // #withReceivableAging receivableAgingFilter, + ARAgingSummaryLoading, // #withReceivableAgingActions toggleFilterARAgingSummary, refreshARAgingSummary, + + // #ownProps + numberFormat, + onNumberFormatSubmit, }) { const handleFilterToggleClick = () => { toggleFilterARAgingSummary(); @@ -37,6 +44,10 @@ function ARAgingSummaryActionsBar({ const handleRecalcReport = () => { refreshARAgingSummary(true); }; + // Handle number format submit. + const handleNumberFormatSubmit = (numberFormat) => { + safeInvoke(onNumberFormatSubmit, numberFormat); + }; return ( @@ -64,6 +75,25 @@ function ARAgingSummaryActionsBar({ /> + + } + minimal={true} + interactionKind={PopoverInteractionKind.CLICK} + position={Position.BOTTOM_LEFT} + > +