From cb4ba39e30009ba731d393c2d6116dfdb7587f60 Mon Sep 17 00:00:00 2001 From: Paul Sealock Date: Fri, 3 Apr 2020 10:54:38 +1300 Subject: [PATCH] Dynamic Currency with Context API (https://github.com/woocommerce/woocommerce-admin/pull/4027) * Make currency setting dynamic with context API * reference Currency * what is 'this' * remove comment * All report tables * Customers report * activity panel * leaderboard test * business details * store details * single source of truth * shipping rates * remove currency-format.js * tidy up * make Currency a factory function * factory revenue table * tables * Chart y-axis labels * customers table * cleanup * business details * shipping * number-format * stock and downloads tables * changelog * cleanup * SQL example: update to dynamic currencies (https://github.com/woocommerce/woocommerce-admin/pull/4033) --- .../components/leaderboard/test/index.js | 26 ++- .../components/report-chart/index.js | 28 ++- .../components/report-filters/index.js | 24 ++- .../components/report-summary/index.js | 9 +- .../analytics/report/categories/table.js | 38 ++-- .../client/analytics/report/coupons/table.js | 35 ++- .../analytics/report/customers/table.js | 37 ++-- .../analytics/report/downloads/table.js | 10 +- .../client/analytics/report/index.js | 12 +- .../client/analytics/report/orders/table.js | 31 ++- .../client/analytics/report/orders/utils.js | 48 ----- .../report/products/table-variations.js | 33 ++- .../client/analytics/report/products/table.js | 39 ++-- .../client/analytics/report/revenue/table.js | 24 ++- .../client/analytics/report/stock/table.js | 26 ++- .../client/analytics/report/taxes/table.js | 32 ++- .../profile-wizard/steps/business-details.js | 18 +- .../profile-wizard/steps/store-details.js | 23 +- .../dashboard/store-performance/index.js | 11 +- .../task-list/tasks/shipping/rates.js | 24 +-- .../header/activity-panel/panels/orders.js | 7 +- .../client/lib/currency-context.js | 31 +++ .../client/lib/currency-format.js | 31 --- .../client/lib/number-format.js | 21 -- .../client/wc-api/reports/utils.js | 4 +- .../extensions/sql-modification/js/index.js | 40 +++- .../packages/currency/CHANGELOG.md | 7 + .../packages/currency/src/index.js | 201 +++++++++--------- .../packages/number/src/index.js | 8 +- 29 files changed, 522 insertions(+), 356 deletions(-) delete mode 100644 plugins/woocommerce-admin/client/analytics/report/orders/utils.js create mode 100644 plugins/woocommerce-admin/client/lib/currency-context.js delete mode 100644 plugins/woocommerce-admin/client/lib/currency-format.js delete mode 100644 plugins/woocommerce-admin/client/lib/number-format.js diff --git a/plugins/woocommerce-admin/client/analytics/components/leaderboard/test/index.js b/plugins/woocommerce-admin/client/analytics/components/leaderboard/test/index.js index 7b61e8a4910..4ac384f80d8 100644 --- a/plugins/woocommerce-admin/client/analytics/components/leaderboard/test/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/leaderboard/test/index.js @@ -6,33 +6,41 @@ import { mount, shallow } from 'enzyme'; /** * WooCommerce dependencies */ -import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency-format'; -import { numberFormat } from 'lib/number-format'; +import { numberFormat } from '@woocommerce/number'; +import Currency from '@woocommerce/currency'; /** * Internal dependencies */ import { Leaderboard } from '../'; import mockData from '../data/top-selling-products-mock-data'; +import { CURRENCY } from '@woocommerce/wc-admin-settings'; + +const { formatCurrency, formatDecimal } = Currency( CURRENCY ); const rows = mockData.map( ( row ) => { - const { name, items_sold: itemsSold, net_revenue: netRevenue, orders_count: ordersCount } = row; + const { + name, + items_sold: itemsSold, + net_revenue: netRevenue, + orders_count: ordersCount, + } = row; return [ { display: '' + name + '', value: name, }, { - display: numberFormat( itemsSold ), + display: numberFormat( CURRENCY, itemsSold ), value: itemsSold, }, { - display: numberFormat( ordersCount ), + display: numberFormat( CURRENCY, ordersCount ), value: ordersCount, }, { display: formatCurrency( netRevenue ), - value: getCurrencyFormatDecimal( netRevenue ), + value: formatDecimal( netRevenue ), }, ]; } ); @@ -85,7 +93,7 @@ describe( 'Leaderboard', () => { expect( firstRow[ 1 ].value ).toBe( mockData[ 0 ].items_sold ); expect( firstRow[ 2 ].value ).toBe( mockData[ 0 ].orders_count ); expect( firstRow[ 3 ].value ).toBe( - getCurrencyFormatDecimal( mockData[ 0 ].net_revenue ) + formatDecimal( mockData[ 0 ].net_revenue ) ); expect( @@ -93,10 +101,10 @@ describe( 'Leaderboard', () => { ).toBe( 5 ); expect( tableItems.at( 0 ).text() ).toBe( mockData[ 0 ].name ); expect( tableItems.at( 1 ).text() ).toBe( - numberFormat( mockData[ 0 ].items_sold ) + numberFormat( CURRENCY, mockData[ 0 ].items_sold ) ); expect( tableItems.at( 2 ).text() ).toBe( - numberFormat( mockData[ 0 ].orders_count ) + numberFormat( CURRENCY, mockData[ 0 ].orders_count ) ); expect( tableItems.at( 3 ).text() ).toBe( formatCurrency( mockData[ 0 ].net_revenue ) diff --git a/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js b/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js index 5c1a119f82b..c8fed1ef620 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-chart/index.js @@ -20,8 +20,8 @@ import { getPreviousDate, } from 'lib/date'; import { Chart } from '@woocommerce/components'; -import { CURRENCY } from '@woocommerce/wc-admin-settings'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; +import { CurrencyContext } from 'lib/currency-context'; /** * Internal dependencies @@ -80,9 +80,18 @@ export class ReportChart extends Component { } getTimeChartData() { - const { query, primaryData, secondaryData, selectedChart, defaultDateRange } = this.props; + const { + query, + primaryData, + secondaryData, + selectedChart, + defaultDateRange, + } = this.props; const currentInterval = getIntervalForQuery( query ); - const { primary, secondary } = getCurrentDates( query, defaultDateRange ); + const { primary, secondary } = getCurrentDates( + query, + defaultDateRange + ); const chartData = primaryData.data.intervals.map( function( interval, @@ -159,6 +168,7 @@ export class ReportChart extends Component { const emptyMessage = emptySearchResults ? __( 'No data for the current search', 'woocommerce-admin' ) : __( 'No data for the selected date range', 'woocommerce-admin' ); + const { formatCurrency, getCurrency } = this.context; return ( ); } @@ -243,6 +254,8 @@ export class ReportChart extends Component { } } +ReportChart.contextType = CurrencyContext; + ReportChart.propTypes = { /** * Filters available for that report. @@ -341,7 +354,10 @@ export default compose( const limitBy = limitProperties || [ endpoint ]; const selectedFilter = getSelectedFilter( filters, query ); const filterParam = get( selectedFilter, [ 'settings', 'param' ] ); - const chartMode = props.mode || getChartMode( selectedFilter, query ) || 'time-comparison'; + const chartMode = + props.mode || + getChartMode( selectedFilter, query ) || + 'time-comparison'; const { woocommerce_default_date_range: defaultDateRange } = select( SETTINGS_STORE_NAME ).getSetting( 'wc_admin', 'wcAdminSettings' ); diff --git a/plugins/woocommerce-admin/client/analytics/components/report-filters/index.js b/plugins/woocommerce-admin/client/analytics/components/report-filters/index.js index fae43c4d15f..76577325aae 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-filters/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-filters/index.js @@ -17,12 +17,12 @@ import { SETTINGS_STORE_NAME } from '@woocommerce/data'; * Internal dependencies */ import { recordEvent } from 'lib/tracks'; -import { Currency } from 'lib/currency-format'; import { getCurrentDates, getDateParamsFromQuery, isoDateFormat, } from 'lib/date'; +import { CurrencyContext } from 'lib/currency-context'; class ReportFilters extends Component { constructor() { @@ -92,12 +92,22 @@ class ReportFilters extends Component { } render() { - const { advancedFilters, filters, path, query, showDatePicker, defaultDateRange } = this.props; - const { period, compare, before, after } = getDateParamsFromQuery( query, defaultDateRange ); - const { primary: primaryDate, secondary: secondaryDate } = getCurrentDates( + const { + advancedFilters, + filters, + path, + query, + showDatePicker, + defaultDateRange, + } = this.props; + const { period, compare, before, after } = getDateParamsFromQuery( query, defaultDateRange ); + const { + primary: primaryDate, + secondary: secondaryDate, + } = getCurrentDates( query, defaultDateRange ); const dateQuery = { period, compare, @@ -106,6 +116,8 @@ class ReportFilters extends Component { primaryDate, secondaryDate, }; + const Currency = this.context; + return ( { +ReportFilters.contextType = CurrencyContext; + +export default withSelect( ( select ) => { const { woocommerce_default_date_range: defaultDateRange } = select( SETTINGS_STORE_NAME ).getSetting( 'wc_admin', 'wcAdminSettings' ); diff --git a/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js b/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js index f9dff86b3cf..f0c459bf99d 100644 --- a/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js +++ b/plugins/woocommerce-admin/client/analytics/components/report-summary/index.js @@ -16,8 +16,7 @@ import { SummaryListPlaceholder, SummaryNumber, } from '@woocommerce/components'; -import { calculateDelta, formatValue } from 'lib/number-format'; -import { formatCurrency } from 'lib/currency-format'; +import { calculateDelta, formatValue } from '@woocommerce/number'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; /** @@ -27,15 +26,17 @@ import { getSummaryNumbers } from 'wc-api/reports/utils'; import ReportError from 'analytics/components/report-error'; import withSelect from 'wc-api/with-select'; import { recordEvent } from 'lib/tracks'; +import { CurrencyContext } from 'lib/currency-context'; /** * Component to render summary numbers in reports. */ export class ReportSummary extends Component { formatVal( val, type ) { + const { formatCurrency, getCurrency } = this.context; return type === 'currency' ? formatCurrency( val ) - : formatValue( type, val ); + : formatValue( getCurrency(), type, val ); } getValues( key, type ) { @@ -192,6 +193,8 @@ ReportSummary.defaultProps = { }, }; +ReportSummary.contextType = CurrencyContext; + export default compose( withSelect( ( select, props ) => { const { diff --git a/plugins/woocommerce-admin/client/analytics/report/categories/table.js b/plugins/woocommerce-admin/client/analytics/report/categories/table.js index dc11152a207..4ed82c740ba 100644 --- a/plugins/woocommerce-admin/client/analytics/report/categories/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/categories/table.js @@ -9,14 +9,9 @@ import { map } from 'lodash'; /** * WooCommerce dependencies */ -import { - formatCurrency, - getCurrencyFormatDecimal, - renderCurrency, -} from 'lib/currency-format'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; import { Link } from '@woocommerce/components'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; /** * Internal dependencies @@ -24,12 +19,14 @@ import { formatValue } from 'lib/number-format'; import CategoryBreacrumbs from './breadcrumbs'; import ReportTable from 'analytics/components/report-table'; import withSelect from 'wc-api/with-select'; +import { CurrencyContext } from 'lib/currency-context'; class CategoriesReportTable extends Component { constructor( props ) { super( props ); this.getRowsContent = this.getRowsContent.bind( this ); + this.getSummary = this.getSummary.bind( this ); } getHeadersContent() { @@ -71,6 +68,13 @@ class CategoriesReportTable extends Component { } getRowsContent( categoryStats ) { + const { + render: renderCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; + const currency = getCurrency(); + return map( categoryStats, ( categoryStat ) => { const { category_id: categoryId, @@ -95,7 +99,7 @@ class CategoriesReportTable extends Component { value: category && category.name, }, { - display: formatValue( 'number', itemsSold ), + display: formatValue( currency, 'number', itemsSold ), value: itemsSold, }, { @@ -115,13 +119,13 @@ class CategoriesReportTable extends Component { ) } type="wc-admin" > - { formatValue( 'number', productsCount ) } + { formatValue( currency, 'number', productsCount ) } ), value: productsCount, }, { - display: formatValue( 'number', ordersCount ), + display: formatValue( currency, 'number', ordersCount ), value: ordersCount, }, ]; @@ -129,7 +133,13 @@ class CategoriesReportTable extends Component { } getSummary( totals, totalResults = 0 ) { - const { items_sold: itemsSold = 0, net_revenue: netRevenue = 0, orders_count: ordersCount = 0 } = totals; + const { + items_sold: itemsSold = 0, + net_revenue: netRevenue = 0, + orders_count: ordersCount = 0, + } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -138,7 +148,7 @@ class CategoriesReportTable extends Component { totalResults, 'woocommerce-admin' ), - value: formatValue( 'number', totalResults ), + value: formatValue( currency, 'number', totalResults ), }, { label: _n( @@ -147,7 +157,7 @@ class CategoriesReportTable extends Component { itemsSold, 'woocommerce-admin' ), - value: formatValue( 'number', itemsSold ), + value: formatValue( currency, 'number', itemsSold ), }, { label: __( 'net sales', 'woocommerce-admin' ), @@ -160,7 +170,7 @@ class CategoriesReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, ]; } @@ -207,6 +217,8 @@ class CategoriesReportTable extends Component { } } +CategoriesReportTable.contextType = CurrencyContext; + export default compose( withSelect( ( select, props ) => { const { isRequesting, query } = props; diff --git a/plugins/woocommerce-admin/client/analytics/report/coupons/table.js b/plugins/woocommerce-admin/client/analytics/report/coupons/table.js index b0ea82baa56..6fe71a45e11 100644 --- a/plugins/woocommerce-admin/client/analytics/report/coupons/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/coupons/table.js @@ -10,17 +10,17 @@ import { map } from 'lodash'; */ import { Date, Link } from '@woocommerce/components'; import { defaultTableDateFormat } from 'lib/date'; -import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency-format'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getSetting } from '@woocommerce/wc-admin-settings'; /** * Internal dependencies */ import ReportTable from 'analytics/components/report-table'; +import { CurrencyContext } from 'lib/currency-context'; -export default class CouponsReportTable extends Component { +class CouponsReportTable extends Component { constructor() { super(); @@ -71,9 +71,18 @@ export default class CouponsReportTable extends Component { const { query } = this.props; const persistedQuery = getPersistedQuery( query ); const dateFormat = getSetting( 'dateFormat', defaultTableDateFormat ); + const { + formatCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; return map( coupons, ( coupon ) => { - const { amount, coupon_id: couponId, orders_count: ordersCount } = coupon; + const { + amount, + coupon_id: couponId, + orders_count: ordersCount, + } = coupon; const extendedInfo = coupon.extended_info || {}; const { code, @@ -102,7 +111,7 @@ export default class CouponsReportTable extends Component { } ); const ordersLink = ( - { formatValue( 'number', ordersCount ) } + { formatValue( getCurrency(), 'number', ordersCount ) } ); @@ -148,7 +157,13 @@ export default class CouponsReportTable extends Component { } getSummary( totals ) { - const { coupons_count: couponsCount = 0, orders_count: ordersCount = 0, amount = 0 } = totals; + const { + coupons_count: couponsCount = 0, + orders_count: ordersCount = 0, + amount = 0, + } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -157,7 +172,7 @@ export default class CouponsReportTable extends Component { couponsCount, 'woocommerce-admin' ), - value: formatValue( 'number', couponsCount ), + value: formatValue( currency, 'number', couponsCount ), }, { label: _n( @@ -166,7 +181,7 @@ export default class CouponsReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, { label: __( 'amount discounted', 'woocommerce-admin' ), @@ -216,3 +231,7 @@ export default class CouponsReportTable extends Component { ); } } + +CouponsReportTable.contextType = CurrencyContext; + +export default CouponsReportTable; diff --git a/plugins/woocommerce-admin/client/analytics/report/customers/table.js b/plugins/woocommerce-admin/client/analytics/report/customers/table.js index ebd369f4c97..03fd52010be 100644 --- a/plugins/woocommerce-admin/client/analytics/report/customers/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/customers/table.js @@ -8,9 +8,8 @@ import { Tooltip } from '@wordpress/components'; /** * WooCommerce dependencies */ -import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency-format'; import { Date, Link } from '@woocommerce/components'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; import { defaultTableDateFormat } from 'lib/date'; @@ -20,8 +19,9 @@ const { countries } = getSetting( 'dataEndpoints', { countries: {} } ); * Internal dependencies */ import ReportTable from 'analytics/components/report-table'; +import { CurrencyContext } from 'lib/currency-context'; -export default class CustomersReportTable extends Component { +class CustomersReportTable extends Component { constructor() { super(); @@ -114,6 +114,11 @@ export default class CustomersReportTable extends Component { getRowsContent( customers ) { const dateFormat = getSetting( 'dateFormat', defaultTableDateFormat ); + const { + formatCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; return customers.map( ( customer ) => { const { @@ -145,19 +150,13 @@ export default class CustomersReportTable extends Component { ); const dateLastActiveDisplay = dateLastActive ? ( - + ) : ( '—' ); const dateRegisteredDisplay = dateRegistered ? ( - + ) : ( '—' ); @@ -193,7 +192,11 @@ export default class CustomersReportTable extends Component { value: email, }, { - display: formatValue( 'number', ordersCount ), + display: formatValue( + getCurrency(), + 'number', + ordersCount + ), value: ordersCount, }, { @@ -231,6 +234,8 @@ export default class CustomersReportTable extends Component { avg_total_spend: avgTotalSpend = 0, avg_avg_order_value: avgAvgOrderValue = 0, } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -239,7 +244,7 @@ export default class CustomersReportTable extends Component { customersCount, 'woocommerce-admin' ), - value: formatValue( 'number', customersCount ), + value: formatValue( currency, 'number', customersCount ), }, { label: _n( @@ -248,7 +253,7 @@ export default class CustomersReportTable extends Component { avgOrdersCount, 'woocommerce-admin' ), - value: formatValue( 'number', avgOrdersCount ), + value: formatValue( currency, 'number', avgOrdersCount ), }, { label: __( 'average lifetime spend', 'woocommerce-admin' ), @@ -294,3 +299,7 @@ export default class CustomersReportTable extends Component { ); } } + +CustomersReportTable.contextType = CurrencyContext; + +export default CustomersReportTable; diff --git a/plugins/woocommerce-admin/client/analytics/report/downloads/table.js b/plugins/woocommerce-admin/client/analytics/report/downloads/table.js index 5fe57b842c2..72aec0d045c 100644 --- a/plugins/woocommerce-admin/client/analytics/report/downloads/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/downloads/table.js @@ -13,7 +13,7 @@ import moment from 'moment'; import { getCurrentDates, defaultTableDateFormat } from 'lib/date'; import { Date, Link } from '@woocommerce/components'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; @@ -21,6 +21,7 @@ import { SETTINGS_STORE_NAME } from '@woocommerce/data'; * Internal dependencies */ import ReportTable from 'analytics/components/report-table'; +import { CurrencyContext } from 'lib/currency-context'; class CouponsReportTable extends Component { constructor() { @@ -150,11 +151,12 @@ class CouponsReportTable extends Component { const after = moment( dates.primary.after ); const before = moment( dates.primary.before ); const days = before.diff( after, 'days' ) + 1; + const currency = this.context.getCurrency(); return [ { label: _n( 'day', 'days', days, 'woocommerce-admin' ), - value: formatValue( 'number', days ), + value: formatValue( currency, 'number', days ), }, { label: _n( @@ -163,7 +165,7 @@ class CouponsReportTable extends Component { downloadCount, 'woocommerce-admin' ), - value: formatValue( 'number', downloadCount ), + value: formatValue( currency, 'number', downloadCount ), }, ]; } @@ -191,6 +193,8 @@ class CouponsReportTable extends Component { } } +CouponsReportTable.contextType = CurrencyContext; + export default withSelect( ( select ) => { const { woocommerce_default_date_range: defaultDateRange } = select( SETTINGS_STORE_NAME diff --git a/plugins/woocommerce-admin/client/analytics/report/index.js b/plugins/woocommerce-admin/client/analytics/report/index.js index cdd6763eaae..9769c3792ae 100644 --- a/plugins/woocommerce-admin/client/analytics/report/index.js +++ b/plugins/woocommerce-admin/client/analytics/report/index.js @@ -31,6 +31,10 @@ import CustomersReport from './customers'; import ReportError from 'analytics/components/report-error'; import { searchItemsByString } from 'wc-api/items/utils'; import withSelect from 'wc-api/with-select'; +import { + CurrencyContext, + getFilteredCurrencyInstance, +} from 'lib/currency-context'; export const REPORTS_FILTER = 'woocommerce_admin_reports_list'; const manageStock = getSetting( 'manageStock', 'no' ); @@ -142,7 +146,13 @@ class Report extends Component { return null; } const Container = report.component; - return ; + return ( + + + + ); } } diff --git a/plugins/woocommerce-admin/client/analytics/report/orders/table.js b/plugins/woocommerce-admin/client/analytics/report/orders/table.js index 75b1c1283a6..595e7adfa3c 100644 --- a/plugins/woocommerce-admin/client/analytics/report/orders/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/orders/table.js @@ -9,8 +9,7 @@ import { map } from 'lodash'; * WooCommerce dependencies */ import { Date, Link, OrderStatus, ViewMoreList } from '@woocommerce/components'; -import { formatCurrency, renderCurrency } from 'lib/currency-format'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getSetting } from '@woocommerce/wc-admin-settings'; import { defaultTableDateFormat } from 'lib/date'; @@ -19,9 +18,10 @@ import { defaultTableDateFormat } from 'lib/date'; */ import ReportTable from 'analytics/components/report-table'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; +import { CurrencyContext } from 'lib/currency-context'; import './style.scss'; -export default class OrdersReportTable extends Component { +class OrdersReportTable extends Component { constructor() { super(); @@ -105,6 +105,7 @@ export default class OrdersReportTable extends Component { const { query } = this.props; const persistedQuery = getPersistedQuery( query ); const dateFormat = getSetting( 'dateFormat', defaultTableDateFormat ); + const { render: renderCurrency, getCurrency } = this.context; return map( tableData, ( row ) => { const { @@ -205,7 +206,11 @@ export default class OrdersReportTable extends Component { .join( ', ' ), }, { - display: formatValue( 'number', numItemsSold ), + display: formatValue( + getCurrency(), + 'number', + numItemsSold + ), value: numItemsSold, }, { @@ -237,6 +242,8 @@ export default class OrdersReportTable extends Component { coupons_count: couponsCount = 0, net_revenue: netRevenue = 0, } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -245,7 +252,7 @@ export default class OrdersReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, { label: _n( @@ -254,7 +261,7 @@ export default class OrdersReportTable extends Component { numNewCustomers, 'woocommerce-admin' ), - value: formatValue( 'number', numNewCustomers ), + value: formatValue( currency, 'number', numNewCustomers ), }, { label: _n( @@ -263,7 +270,7 @@ export default class OrdersReportTable extends Component { numReturningCustomers, 'woocommerce-admin' ), - value: formatValue( 'number', numReturningCustomers ), + value: formatValue( currency, 'number', numReturningCustomers ), }, { label: _n( @@ -272,7 +279,7 @@ export default class OrdersReportTable extends Component { products, 'woocommerce-admin' ), - value: formatValue( 'number', products ), + value: formatValue( currency, 'number', products ), }, { label: _n( @@ -281,7 +288,7 @@ export default class OrdersReportTable extends Component { numItemsSold, 'woocommerce-admin' ), - value: formatValue( 'number', numItemsSold ), + value: formatValue( currency, 'number', numItemsSold ), }, { label: _n( @@ -290,7 +297,7 @@ export default class OrdersReportTable extends Component { couponsCount, 'woocommerce-admin' ), - value: formatValue( 'number', couponsCount ), + value: formatValue( currency, 'number', couponsCount ), }, { label: __( 'net sales', 'woocommerce-admin' ), @@ -348,3 +355,7 @@ export default class OrdersReportTable extends Component { ); } } + +OrdersReportTable.contextType = CurrencyContext; + +export default OrdersReportTable; diff --git a/plugins/woocommerce-admin/client/analytics/report/orders/utils.js b/plugins/woocommerce-admin/client/analytics/report/orders/utils.js deleted file mode 100644 index 70d7a41cad3..00000000000 --- a/plugins/woocommerce-admin/client/analytics/report/orders/utils.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * External dependencies - */ - -/** - * WooCommerce dependencies - */ -import { getCurrencyFormatDecimal } from 'lib/currency-format'; -import { getOrderRefundTotal } from 'lib/order-values'; - -export function formatTableOrders( orders ) { - return orders.map( ( order ) => { - const { - date_created: date, - id, - status, - customer_id: customerId, - line_items: lineItems, - coupon_lines: couponLines, - currency, - total, - total_tax: totalTax, - shipping_total: shippingTotal, - discount_total: discountTotal, - } = order; - - return { - date, - id, - status, - customer_id: customerId, - line_items: lineItems, - items_sold: lineItems.reduce( - ( acc, item ) => item.quantity + acc, - 0 - ), - coupon_lines: couponLines, - currency, - net_revenue: getCurrencyFormatDecimal( - total - - totalTax - - shippingTotal - - discountTotal + - getOrderRefundTotal( order ) - ), - }; - } ); -} diff --git a/plugins/woocommerce-admin/client/analytics/report/products/table-variations.js b/plugins/woocommerce-admin/client/analytics/report/products/table-variations.js index 8c81ea6be23..bed87ef9425 100644 --- a/plugins/woocommerce-admin/client/analytics/report/products/table-variations.js +++ b/plugins/woocommerce-admin/client/analytics/report/products/table-variations.js @@ -9,9 +9,8 @@ import { map, get } from 'lodash'; * WooCommerce dependencies */ import { Link } from '@woocommerce/components'; -import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency-format'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; /** @@ -19,16 +18,18 @@ import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; */ import ReportTable from 'analytics/components/report-table'; import { isLowStock } from './utils'; +import { CurrencyContext } from 'lib/currency-context'; const manageStock = getSetting( 'manageStock', 'no' ); const stockStatuses = getSetting( 'stockStatuses', {} ); -export default class VariationsReportTable extends Component { +class VariationsReportTable extends Component { constructor() { super(); this.getHeadersContent = this.getHeadersContent.bind( this ); this.getRowsContent = this.getRowsContent.bind( this ); + this.getSummary = this.getSummary.bind( this ); } getHeadersContent() { @@ -86,9 +87,19 @@ export default class VariationsReportTable extends Component { getRowsContent( data = [] ) { const { query } = this.props; const persistedQuery = getPersistedQuery( query ); + const { + formatCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; return map( data, ( row ) => { - const { items_sold: itemsSold, net_revenue: netRevenue, orders_count: ordersCount, product_id: productId } = row; + const { + items_sold: itemsSold, + net_revenue: netRevenue, + orders_count: ordersCount, + product_id: productId, + } = row; const extendedInfo = row.extended_info || {}; const { stock_status: stockStatus, @@ -123,7 +134,7 @@ export default class VariationsReportTable extends Component { value: sku, }, { - display: formatValue( 'number', itemsSold ), + display: formatValue( getCurrency(), 'number', itemsSold ), value: itemsSold, }, { @@ -175,6 +186,8 @@ export default class VariationsReportTable extends Component { net_revenue: netRevenue = 0, orders_count: ordersCount = 0, } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -183,7 +196,7 @@ export default class VariationsReportTable extends Component { variationsCount, 'woocommerce-admin' ), - value: formatValue( 'number', variationsCount ), + value: formatValue( currency, 'number', variationsCount ), }, { label: _n( @@ -192,7 +205,7 @@ export default class VariationsReportTable extends Component { itemsSold, 'woocommerce-admin' ), - value: formatValue( 'number', itemsSold ), + value: formatValue( currency, 'number', itemsSold ), }, { label: __( 'net sales', 'woocommerce-admin' ), @@ -205,7 +218,7 @@ export default class VariationsReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, ]; } @@ -265,3 +278,7 @@ export default class VariationsReportTable extends Component { ); } } + +VariationsReportTable.contextType = CurrencyContext; + +export default VariationsReportTable; diff --git a/plugins/woocommerce-admin/client/analytics/report/products/table.js b/plugins/woocommerce-admin/client/analytics/report/products/table.js index 755c91e45de..3e991f38c56 100644 --- a/plugins/woocommerce-admin/client/analytics/report/products/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/products/table.js @@ -10,14 +10,9 @@ import { map } from 'lodash'; /** * WooCommerce dependencies */ -import { - formatCurrency, - getCurrencyFormatDecimal, - renderCurrency, -} from 'lib/currency-format'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; import { Link, Tag } from '@woocommerce/components'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; /** @@ -27,6 +22,7 @@ import CategoryBreacrumbs from '../categories/breadcrumbs'; import { isLowStock } from './utils'; import ReportTable from 'analytics/components/report-table'; import withSelect from 'wc-api/with-select'; +import { CurrencyContext } from 'lib/currency-context'; import './style.scss'; const manageStock = getSetting( 'manageStock', 'no' ); @@ -38,6 +34,7 @@ class ProductsReportTable extends Component { this.getHeadersContent = this.getHeadersContent.bind( this ); this.getRowsContent = this.getRowsContent.bind( this ); + this.getSummary = this.getSummary.bind( this ); } getHeadersContent() { @@ -105,6 +102,12 @@ class ProductsReportTable extends Component { getRowsContent( data = [] ) { const { query } = this.props; const persistedQuery = getPersistedQuery( query ); + const { + render: renderCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; + const currency = getCurrency(); return map( data, ( row ) => { const { @@ -185,7 +188,7 @@ class ProductsReportTable extends Component { value: sku, }, { - display: formatValue( 'number', itemsSold ), + display: formatValue( currency, 'number', itemsSold ), value: itemsSold, }, { @@ -238,7 +241,11 @@ class ProductsReportTable extends Component { .join( ', ' ), }, { - display: formatValue( 'number', variations.length ), + display: formatValue( + currency, + 'number', + variations.length + ), value: variations.length, }, manageStock === 'yes' @@ -254,7 +261,11 @@ class ProductsReportTable extends Component { manageStock === 'yes' ? { display: extendedInfoManageStock - ? formatValue( 'number', stockQuantity ) + ? formatValue( + currency, + 'number', + stockQuantity + ) : __( 'N/A', 'woocommerce-admin' ), value: stockQuantity, } @@ -270,6 +281,8 @@ class ProductsReportTable extends Component { net_revenue: netRevenue = 0, orders_count: ordersCount = 0, } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -278,7 +291,7 @@ class ProductsReportTable extends Component { productsCount, 'woocommerce-admin' ), - value: formatValue( 'number', productsCount ), + value: formatValue( currency, 'number', productsCount ), }, { label: _n( @@ -287,7 +300,7 @@ class ProductsReportTable extends Component { itemsSold, 'woocommerce-admin' ), - value: formatValue( 'number', itemsSold ), + value: formatValue( currency, 'number', itemsSold ), }, { label: __( 'net sales', 'woocommerce-admin' ), @@ -300,7 +313,7 @@ class ProductsReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, ]; } @@ -360,6 +373,8 @@ class ProductsReportTable extends Component { } } +ProductsReportTable.contextType = CurrencyContext; + export default compose( withSelect( ( select, props ) => { const { query, isRequesting } = props; diff --git a/plugins/woocommerce-admin/client/analytics/report/revenue/table.js b/plugins/woocommerce-admin/client/analytics/report/revenue/table.js index d741e92e2d9..a46667fb3b2 100644 --- a/plugins/woocommerce-admin/client/analytics/report/revenue/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/revenue/table.js @@ -16,12 +16,7 @@ import { getCurrentDates, } from 'lib/date'; import { Date, Link } from '@woocommerce/components'; -import { - formatCurrency, - getCurrencyFormatDecimal, - renderCurrency, -} from 'lib/currency-format'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getSetting } from '@woocommerce/wc-admin-settings'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; @@ -32,6 +27,7 @@ import { QUERY_DEFAULTS } from 'wc-api/constants'; import ReportTable from 'analytics/components/report-table'; import withSelect from 'wc-api/with-select'; import { getReportTableQuery } from 'wc-api/reports/utils'; +import { CurrencyContext } from 'lib/currency-context'; class RevenueReportTable extends Component { constructor() { @@ -113,6 +109,12 @@ class RevenueReportTable extends Component { getRowsContent( data = [] ) { const dateFormat = getSetting( 'dateFormat', defaultTableDateFormat ); + const { + formatCurrency, + render: renderCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; return data.map( ( row ) => { const { @@ -136,7 +138,7 @@ class RevenueReportTable extends Component { } type="wp-admin" > - { formatValue( 'number', ordersCount ) } + { formatValue( getCurrency(), 'number', ordersCount ) } ); return [ @@ -196,10 +198,12 @@ class RevenueReportTable extends Component { shipping = 0, net_revenue: netRevenue = 0, } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( 'day', 'days', totalResults, 'woocommerce-admin' ), - value: formatValue( 'number', totalResults ), + value: formatValue( currency, 'number', totalResults ), }, { label: _n( @@ -208,7 +212,7 @@ class RevenueReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, { label: __( 'gross sales', 'woocommerce-admin' ), @@ -271,6 +275,8 @@ class RevenueReportTable extends Component { } } +RevenueReportTable.contextType = CurrencyContext; + export default compose( withSelect( ( select, props ) => { const { query, filters, advancedFilters } = props; diff --git a/plugins/woocommerce-admin/client/analytics/report/stock/table.js b/plugins/woocommerce-admin/client/analytics/report/stock/table.js index c02205ade05..365aeb11aa0 100644 --- a/plugins/woocommerce-admin/client/analytics/report/stock/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/stock/table.js @@ -10,7 +10,7 @@ import { decodeEntities } from '@wordpress/html-entities'; */ import { Link } from '@woocommerce/components'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; /** @@ -18,10 +18,11 @@ import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; */ import ReportTable from 'analytics/components/report-table'; import { isLowStock } from './utils'; +import { CurrencyContext } from 'lib/currency-context'; const stockStatuses = getSetting( 'stockStatuses', {} ); -export default class StockReportTable extends Component { +class StockReportTable extends Component { constructor() { super(); @@ -126,7 +127,11 @@ export default class StockReportTable extends Component { }, { display: manageStock - ? formatValue( 'number', stockQuantity ) + ? formatValue( + this.context.getCurrency(), + 'number', + stockQuantity + ) : __( 'N/A', 'woocommerce-admin' ), value: stockQuantity, }, @@ -142,6 +147,7 @@ export default class StockReportTable extends Component { instock = 0, onbackorder = 0, } = totals; + const currency = this.context.getCurrency(); return [ { label: _n( @@ -150,23 +156,23 @@ export default class StockReportTable extends Component { products, 'woocommerce-admin' ), - value: formatValue( 'number', products ), + value: formatValue( currency, 'number', products ), }, { label: __( 'out of stock', outofstock, 'woocommerce-admin' ), - value: formatValue( 'number', outofstock ), + value: formatValue( currency, 'number', outofstock ), }, { label: __( 'low stock', lowstock, 'woocommerce-admin' ), - value: formatValue( 'number', lowstock ), + value: formatValue( 'currency, number', lowstock ), }, { label: __( 'on backorder', onbackorder, 'woocommerce-admin' ), - value: formatValue( 'number', onbackorder ), + value: formatValue( currency, 'number', onbackorder ), }, { label: __( 'in stock', instock, 'woocommerce-admin' ), - value: formatValue( 'number', instock ), + value: formatValue( currency, 'number', instock ), }, ]; } @@ -200,3 +206,7 @@ export default class StockReportTable extends Component { ); } } + +StockReportTable.contextType = CurrencyContext; + +export default StockReportTable; diff --git a/plugins/woocommerce-admin/client/analytics/report/taxes/table.js b/plugins/woocommerce-admin/client/analytics/report/taxes/table.js index 6a58d1e70f9..94968566f19 100644 --- a/plugins/woocommerce-admin/client/analytics/report/taxes/table.js +++ b/plugins/woocommerce-admin/client/analytics/report/taxes/table.js @@ -9,21 +9,17 @@ import { map } from 'lodash'; * WooCommerce dependencies */ import { Link } from '@woocommerce/components'; -import { - formatCurrency, - getCurrencyFormatDecimal, - renderCurrency, -} from 'lib/currency-format'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; import { getTaxCode } from './utils'; -import { formatValue } from 'lib/number-format'; +import { formatValue } from '@woocommerce/number'; /** * Internal dependencies */ import ReportTable from 'analytics/components/report-table'; +import { CurrencyContext } from 'lib/currency-context'; -export default class TaxesReportTable extends Component { +class TaxesReportTable extends Component { constructor() { super(); @@ -74,6 +70,12 @@ export default class TaxesReportTable extends Component { } getRowsContent( taxes ) { + const { + render: renderCurrency, + formatDecimal: getCurrencyFormatDecimal, + getCurrency, + } = this.context; + return map( taxes, ( tax ) => { const { query } = this.props; const { @@ -123,7 +125,11 @@ export default class TaxesReportTable extends Component { value: getCurrencyFormatDecimal( shippingTax ), }, { - display: formatValue( 'number', ordersCount ), + display: formatValue( + getCurrency(), + 'number', + ordersCount + ), value: ordersCount, }, ]; @@ -138,6 +144,8 @@ export default class TaxesReportTable extends Component { shipping_tax: shippingTax = 0, orders_count: ordersCount = 0, } = totals; + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return [ { label: _n( @@ -146,7 +154,7 @@ export default class TaxesReportTable extends Component { taxesCodes, 'woocommerce-admin' ), - value: formatValue( 'number', taxesCodes ), + value: formatValue( currency, 'number', taxesCodes ), }, { label: __( 'total tax', 'woocommerce-admin' ), @@ -167,7 +175,7 @@ export default class TaxesReportTable extends Component { ordersCount, 'woocommerce-admin' ), - value: formatValue( 'number', ordersCount ), + value: formatValue( currency, 'number', ordersCount ), }, ]; } @@ -204,3 +212,7 @@ export default class TaxesReportTable extends Component { ); } } + +TaxesReportTable.contextType = CurrencyContext; + +export default TaxesReportTable; diff --git a/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/business-details.js b/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/business-details.js index 07c4cb32ed9..032267b8045 100644 --- a/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/business-details.js +++ b/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/business-details.js @@ -11,11 +11,8 @@ import { keys, get, pickBy } from 'lodash'; /** * WooCommerce dependencies */ -import { formatValue } from 'lib/number-format'; -import { - getSetting, - CURRENCY as currency, -} from '@woocommerce/wc-admin-settings'; +import { formatValue } from '@woocommerce/number'; +import { getSetting } from '@woocommerce/wc-admin-settings'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; /** @@ -30,10 +27,10 @@ import { } from '@woocommerce/components'; import withWCApiSelect from 'wc-api/with-select'; import { recordEvent } from 'lib/tracks'; -import { formatCurrency } from 'lib/currency-format'; import Plugins from 'dashboard/task-list/tasks/steps/plugins'; import { pluginNames } from 'wc-api/onboarding/constants'; import { getCurrencyRegion } from 'dashboard/utils'; +import { CurrencyContext } from 'lib/currency-context'; const wcAdminAssetUrl = getSetting( 'wcAdminAssetUrl', '' ); @@ -95,11 +92,12 @@ class BusinessDetails extends Component { selling_venues: sellingVenues, } = values; const businessExtensions = this.getBusinessExtensions( values ); + const { getCurrency } = this.context; recordEvent( 'storeprofiler_store_business_details_continue', { product_number: productCount, already_selling: sellingVenues, - currency: currency.code, + currency: getCurrency().code, revenue, used_platform: otherPlatform, used_platform_name: otherPlatformName, @@ -247,7 +245,8 @@ class BusinessDetails extends Component { } numberFormat( value ) { - return formatValue( 'number', value ); + const { getCurrency } = this.context; + return formatValue( getCurrency(), 'number', value ); } getNumberRangeString( min, max = false, format = this.numberFormat ) { @@ -409,6 +408,7 @@ class BusinessDetails extends Component { render() { const { isInstallingExtensions, extensionInstallError } = this.state; + const { formatCurrency } = this.context; const productCountOptions = [ { key: '0', @@ -684,6 +684,8 @@ class BusinessDetails extends Component { } } +BusinessDetails.contextType = CurrencyContext; + export default compose( withWCApiSelect( ( select ) => { const { getProfileItems, getProfileItemsError } = select( 'wc-api' ); diff --git a/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/store-details.js b/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/store-details.js index 2fca1c81c0c..e9fab183c66 100644 --- a/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/store-details.js +++ b/plugins/woocommerce-admin/client/dashboard/profile-wizard/steps/store-details.js @@ -19,7 +19,6 @@ import { SETTINGS_STORE_NAME } from '@woocommerce/data'; /** * Internal dependencies */ -import { setCurrency } from 'lib/currency-format'; import { getCountryCode, getCurrencyRegion } from 'dashboard/utils'; import { StoreAddress, @@ -27,6 +26,7 @@ import { } from '../../components/settings/general/store-address'; import UsageModal from './usage-modal'; import withWCApiSelect from 'wc-api/with-select'; +import { CurrencyContext } from 'lib/currency-context'; class StoreDetails extends Component { constructor( props ) { @@ -91,7 +91,8 @@ class StoreDetails extends Component { const currencySettings = this.deriveCurrencySettings( values.countryState ); - setCurrency( currencySettings ); + const Currency = this.context; + Currency.setCurrency( currencySettings ); recordEvent( 'storeprofiler_store_details_continue', { store_country: getCountryCode( values.countryState ), @@ -203,8 +204,10 @@ class StoreDetails extends Component { } } +StoreDetails.contextType = CurrencyContext; + export default compose( - withWCApiSelect( select => { + withWCApiSelect( ( select ) => { const { getProfileItemsError, getProfileItems } = select( 'wc-api' ); const profileItems = getProfileItems(); @@ -215,10 +218,12 @@ export default compose( profileItems, }; } ), - withSelect( select => { - const { getSettings, getSettingsError, isGetSettingsRequesting } = select( - SETTINGS_STORE_NAME - ); + withSelect( ( select ) => { + const { + getSettings, + getSettingsError, + isGetSettingsRequesting, + } = select( SETTINGS_STORE_NAME ); const { general: settings = {} } = getSettings( 'general' ); const isSettingsError = Boolean( getSettingsError( 'general' ) ); @@ -233,7 +238,9 @@ export default compose( withDispatch( ( dispatch ) => { const { createNotice } = dispatch( 'core/notices' ); const { updateProfileItems } = dispatch( 'wc-api' ); - const { updateAndPersistSettingsForGroup } = dispatch( SETTINGS_STORE_NAME ); + const { updateAndPersistSettingsForGroup } = dispatch( + SETTINGS_STORE_NAME + ); return { createNotice, diff --git a/plugins/woocommerce-admin/client/dashboard/store-performance/index.js b/plugins/woocommerce-admin/client/dashboard/store-performance/index.js index 40417bdd58e..fb3ed77075d 100644 --- a/plugins/woocommerce-admin/client/dashboard/store-performance/index.js +++ b/plugins/woocommerce-admin/client/dashboard/store-performance/index.js @@ -17,8 +17,7 @@ import { getDateParamsFromQuery, } from 'lib/date'; import { getNewPath, getPersistedQuery } from '@woocommerce/navigation'; -import { calculateDelta, formatValue } from 'lib/number-format'; -import { formatCurrency } from 'lib/currency-format'; +import { calculateDelta, formatValue } from '@woocommerce/number'; import { getSetting } from '@woocommerce/wc-admin-settings'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; @@ -37,6 +36,7 @@ import { import withSelect from 'wc-api/with-select'; import './style.scss'; import { recordEvent } from 'lib/tracks'; +import { CurrencyContext } from 'lib/currency-context'; const { performanceIndicators: indicators } = getSetting( 'dataEndpoints', { performanceIndicators: '', @@ -141,6 +141,8 @@ class StorePerformance extends Component { compare === 'previous_period' ? __( 'Previous Period:', 'woocommerce-admin' ) : __( 'Previous Year:', 'woocommerce-admin' ); + const { formatCurrency, getCurrency } = this.context; + const currency = getCurrency(); return ( { () => @@ -178,12 +180,14 @@ class StorePerformance extends Component { const primaryValue = isCurrency ? formatCurrency( primaryItem.value ) : formatValue( + currency, primaryItem.format, primaryItem.value ); const secondaryValue = isCurrency ? formatCurrency( secondaryItem.value ) : formatValue( + currency, secondaryItem.format, secondaryItem.value ); @@ -229,6 +233,9 @@ class StorePerformance extends Component { ); } } + +StorePerformance.contextType = CurrencyContext; + export default compose( withSelect( ( select, props ) => { const { hiddenBlocks, query } = props; diff --git a/plugins/woocommerce-admin/client/dashboard/task-list/tasks/shipping/rates.js b/plugins/woocommerce-admin/client/dashboard/task-list/tasks/shipping/rates.js index 6785de3c539..27a4c622022 100644 --- a/plugins/woocommerce-admin/client/dashboard/task-list/tasks/shipping/rates.js +++ b/plugins/woocommerce-admin/client/dashboard/task-list/tasks/shipping/rates.js @@ -11,19 +11,13 @@ import PropTypes from 'prop-types'; * WooCommerce dependencies */ import { Flag, Form, TextControlWithAffixes } from '@woocommerce/components'; -import { - CURRENCY, - getSetting, - setSetting, -} from '@woocommerce/wc-admin-settings'; +import { getSetting, setSetting } from '@woocommerce/wc-admin-settings'; /** * Internal dependencies */ -import { getCurrencyFormatString } from 'lib/currency-format'; import { recordEvent } from 'lib/tracks'; - -const { symbol, symbolPosition } = CURRENCY; +import { CurrencyContext } from 'lib/currency-context'; class ShippingRates extends Component { constructor() { @@ -132,6 +126,7 @@ class ShippingRates extends Component { } renderInputPrefix() { + const { symbolPosition, symbol } = this.context.getCurrency(); if ( symbolPosition.indexOf( 'right' ) === 0 ) { return null; } @@ -143,6 +138,7 @@ class ShippingRates extends Component { } renderInputSuffix( rate ) { + const { symbolPosition, symbol } = this.context.getCurrency(); if ( symbolPosition.indexOf( 'right' ) === 0 ) { return ( @@ -159,15 +155,17 @@ class ShippingRates extends Component { } getFormattedRate( value ) { - const currencyString = getCurrencyFormatString( value ); + const { formatDecimalString } = this.context; + const currencyString = formatDecimalString( value ); if ( ! value.length || ! currencyString.length ) { - return getCurrencyFormatString( 0 ); + return formatDecimalString( 0 ); } - return getCurrencyFormatString( value ); + return formatDecimalString( value ); } getInitialValues() { + const { formatDecimalString } = this.context; const values = {}; this.props.shippingZones.forEach( ( zone ) => { @@ -177,7 +175,7 @@ class ShippingRates extends Component { ? this.getFormattedRate( shippingMethods[ 0 ].settings.cost.value ) - : getCurrencyFormatString( 0 ); + : formatDecimalString( 0 ); values[ `${ zone.id }_rate` ] = rate; if ( shippingMethods.length && shippingMethods[ 0 ].enabled ) { @@ -346,4 +344,6 @@ ShippingRates.defaultProps = { shippingZones: [], }; +ShippingRates.contextType = CurrencyContext; + export default ShippingRates; diff --git a/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js b/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js index 830e93e4304..8586df6a751 100644 --- a/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js +++ b/plugins/woocommerce-admin/client/header/activity-panel/panels/orders.js @@ -20,7 +20,6 @@ import { OrderStatus, Section, } from '@woocommerce/components'; -import { formatCurrency } from 'lib/currency-format'; import { getNewPath } from '@woocommerce/navigation'; import { getAdminLink, getSetting } from '@woocommerce/wc-admin-settings'; import { SETTINGS_STORE_NAME } from '@woocommerce/data'; @@ -34,6 +33,7 @@ import ActivityOutboundLink from '../activity-outbound-link'; import { QUERY_DEFAULTS } from 'wc-api/constants'; import { DEFAULT_ACTIONABLE_STATUSES } from 'analytics/settings/config'; import withSelect from 'wc-api/with-select'; +import { CurrencyContext } from 'lib/currency-context'; class OrdersPanel extends Component { renderEmptyCard() { @@ -85,6 +85,7 @@ class OrdersPanel extends Component { renderOrders() { const { orders } = this.props; + const Currency = this.context; if ( orders.length === 0 ) { return this.renderEmptyCard(); @@ -194,7 +195,7 @@ class OrdersPanel extends Component { productsCount ) } - { formatCurrency( total ) } + { Currency.formatCurrency( total ) } } actions={ @@ -304,6 +305,8 @@ OrdersPanel.defaultProps = { isRequesting: false, }; +OrdersPanel.contextType = CurrencyContext; + export default compose( withSelect( ( select, props ) => { const { hasActionableOrders } = props; diff --git a/plugins/woocommerce-admin/client/lib/currency-context.js b/plugins/woocommerce-admin/client/lib/currency-context.js new file mode 100644 index 00000000000..cec306f9a37 --- /dev/null +++ b/plugins/woocommerce-admin/client/lib/currency-context.js @@ -0,0 +1,31 @@ +/** + * External dependencies + */ +import { createContext } from '@wordpress/element'; +import { applyFilters } from '@wordpress/hooks'; + +/** + * WooCommerce dependencies + */ +import Currency from '@woocommerce/currency'; + +/** + * Internal dependencies + */ +import { CURRENCY } from '@woocommerce/wc-admin-settings'; + +const appCurrency = Currency( CURRENCY ); + +export const getFilteredCurrencyInstance = ( query ) => { + const config = appCurrency.getCurrency(); + const filteredConfig = applyFilters( + 'woocommerce_admin_report_currency', + config, + query + ); + return new Currency( filteredConfig ); +}; + +export const CurrencyContext = createContext( + appCurrency // default value +); diff --git a/plugins/woocommerce-admin/client/lib/currency-format.js b/plugins/woocommerce-admin/client/lib/currency-format.js deleted file mode 100644 index 1b0ec03e848..00000000000 --- a/plugins/woocommerce-admin/client/lib/currency-format.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Internal dependencies - */ -import { CURRENCY } from '@woocommerce/wc-admin-settings'; - -/** - * WooCommerce dependencies - */ -import Currency from '@woocommerce/currency'; - -// Pass the site currency settings to our instance. -const storeCurrency = new Currency( CURRENCY ); - -// Allow our exported API to be called without knowing about the Currency instance. -const formatCurrency = storeCurrency.formatCurrency.bind( storeCurrency ); -const formatDecimal = storeCurrency.formatDecimal.bind( storeCurrency ); -const formatDecimalString = storeCurrency.formatDecimalString.bind( - storeCurrency -); -const render = storeCurrency.render.bind( storeCurrency ); -const setCurrency = storeCurrency.setCurrency.bind( storeCurrency ); - -// Export the expected API for the consuming app, along with the instance. -export { - storeCurrency as Currency, - formatCurrency, - formatDecimal as getCurrencyFormatDecimal, - formatDecimalString as getCurrencyFormatString, - render as renderCurrency, - setCurrency, -}; diff --git a/plugins/woocommerce-admin/client/lib/number-format.js b/plugins/woocommerce-admin/client/lib/number-format.js deleted file mode 100644 index 5c54e880c0f..00000000000 --- a/plugins/woocommerce-admin/client/lib/number-format.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * External dependencies - */ -import { partial } from 'lodash'; - -/** - * WooCommerce dependencies - */ -import { CURRENCY } from '@woocommerce/wc-admin-settings'; -import { numberFormat, formatValue, calculateDelta } from '@woocommerce/number'; - -// Compose the site currency settings with the format functions. -const storeNumberFormat = partial( numberFormat, CURRENCY ); -const storeFormatValue = partial( formatValue, CURRENCY ); - -// Export the expected API for the consuming app. -export { - storeNumberFormat as numberFormat, - storeFormatValue as formatValue, - calculateDelta, -}; diff --git a/plugins/woocommerce-admin/client/wc-api/reports/utils.js b/plugins/woocommerce-admin/client/wc-api/reports/utils.js index 4c98807c4dc..1561e8fd30f 100644 --- a/plugins/woocommerce-admin/client/wc-api/reports/utils.js +++ b/plugins/woocommerce-admin/client/wc-api/reports/utils.js @@ -17,7 +17,6 @@ import { getActiveFiltersFromQuery, getUrlKey, } from '@woocommerce/navigation'; -import { formatCurrency } from 'lib/currency-format'; /** * Internal dependencies @@ -388,9 +387,10 @@ export function getReportChartData( options ) { * Returns a formatting function or string to be used by d3-format * * @param {string} type Type of number, 'currency', 'number', 'percent', 'average' + * @param {Function} formatCurrency format currency function * @return {string|Function} returns a number format based on the type or an overriding formatting function */ -export function getTooltipValueFormat( type ) { +export function getTooltipValueFormat( type, formatCurrency ) { switch ( type ) { case 'currency': return formatCurrency; diff --git a/plugins/woocommerce-admin/docs/examples/extensions/sql-modification/js/index.js b/plugins/woocommerce-admin/docs/examples/extensions/sql-modification/js/index.js index e06cea4655a..baff152105b 100644 --- a/plugins/woocommerce-admin/docs/examples/extensions/sql-modification/js/index.js +++ b/plugins/woocommerce-admin/docs/examples/extensions/sql-modification/js/index.js @@ -91,10 +91,14 @@ const addTableColumn = ( reportTableData ) => { ]; const newRows = reportTableData.rows.map( ( row, index ) => { const item = reportTableData.items.data[ index ]; + const currency = + reportTableData.endpoint === 'revenue' + ? item.subtotals.currency + : item.currency; const newRow = [ { - display: item.currency, - value: item.currency, + display: currency, + value: currency, }, ...row, ]; @@ -126,3 +130,35 @@ addFilter( 'plugin-domain', persistQueries ); + +const currencies = { + ZAR: { + code: 'ZAR', + symbol: 'R', + symbolPosition: 'left', + thousandSeparator: ' ', + decimalSeparator: ',', + precision: 2, + }, + NZD: { + code: 'NZD', + symbol: '$NZ', + symbolPosition: 'left', + thousandSeparator: ',', + decimalSeparator: '.', + precision: 2, + }, +}; + +const updateReportCurrencies = ( config, { currency } ) => { + if ( currency && currencies[ currency ] ) { + return currencies[ currency ]; + } + return config; +}; + +addFilter( + 'woocommerce_admin_report_currency', + 'plugin-domain', + updateReportCurrencies +); diff --git a/plugins/woocommerce-admin/packages/currency/CHANGELOG.md b/plugins/woocommerce-admin/packages/currency/CHANGELOG.md index c3a54320a59..1db787ee587 100644 --- a/plugins/woocommerce-admin/packages/currency/CHANGELOG.md +++ b/plugins/woocommerce-admin/packages/currency/CHANGELOG.md @@ -1,3 +1,10 @@ +# 3.0.0 (unreleased) + +## Breaking changes +- Currency is now a factory function instead of a class. + +- Add getCurrency method to retrieve currency config. + # 2.0.0 ## Breaking changes diff --git a/plugins/woocommerce-admin/packages/currency/src/index.js b/plugins/woocommerce-admin/packages/currency/src/index.js index a66e37f941c..799efda03a9 100644 --- a/plugins/woocommerce-admin/packages/currency/src/index.js +++ b/plugins/woocommerce-admin/packages/currency/src/index.js @@ -8,48 +8,59 @@ import { sprintf } from '@wordpress/i18n'; */ import { numberFormat } from '@woocommerce/number'; -export default class Currency { - constructor( currency = null ) { - if ( ! this.code ) { - this.setCurrency( currency ); - } - } +const Currency = ( currencySetting ) => { + let currency; - /** - * Set the currency configuration to use for the class. - * - * @param {Object} currency An object containing currency configuration settings. - */ - setCurrency( currency ) { + setCurrency( currencySetting ); + + function setCurrency( setting ) { const defaultCurrency = getCurrencyData().US; - const config = { ...defaultCurrency, ...currency }; - - this.code = config.code.toString(); - this.symbol = config.symbol.toString(); - this.symbolPosition = config.symbolPosition.toString(); - this.decimalSeparator = config.decimalSeparator.toString(); - this.priceFormat = this.getPriceFormat( config ); - this.thousandSeparator = config.thousandSeparator.toString(); - - const precisionNumber = parseInt( config.precision, 10 ); - this.precision = precisionNumber; + const config = { ...defaultCurrency, ...setting }; + currency = { + code: config.code.toString(), + symbol: config.symbol.toString(), + symbolPosition: config.symbolPosition.toString(), + decimalSeparator: config.decimalSeparator.toString(), + priceFormat: getPriceFormat( config ), + thousandSeparator: config.thousandSeparator.toString(), + precision: parseInt( config.precision, 10 ), + }; } - stripTags( str ) { + function stripTags( str ) { const tmp = document.createElement( 'DIV' ); tmp.innerHTML = str; return tmp.textContent || tmp.innerText || ''; } + /** + * Formats money value. + * + * @param {number|string} number number to format + * @return {?string} A formatted string. + */ + function formatCurrency( number ) { + const formattedNumber = numberFormat( currency, number ); + + if ( formattedNumber === '' ) { + return formattedNumber; + } + + const { priceFormat, symbol } = currency; + + // eslint-disable-next-line @wordpress/valid-sprintf + return sprintf( priceFormat, symbol, formattedNumber ); + } + /** * Get the default price format from a currency. * * @param {Object} config Currency configuration. * @return {string} Price format. */ - getPriceFormat( config ) { + function getPriceFormat( config ) { if ( config.priceFormat ) { - return this.stripTags( config.priceFormat.toString() ); + return stripTags( config.priceFormat.toString() ); } switch ( config.symbolPosition ) { @@ -66,80 +77,76 @@ export default class Currency { return '%1$s%2$s'; } - /** - * Formats money value. - * - * @param {number|string} number number to format - * @return {?string} A formatted string. - */ - formatCurrency( number ) { - const formattedNumber = numberFormat( this, number ); + return { + getCurrency: () => { + return { ...currency }; + }, + setCurrency, + formatCurrency, + getPriceFormat, - if ( formattedNumber === '' ) { - return formattedNumber; - } - - // eslint-disable-next-line @wordpress/valid-sprintf - return sprintf( this.priceFormat, this.symbol, formattedNumber ); - } - - /** - * Get the rounded decimal value of a number at the precision used for the current currency. - * This is a work-around for fraction-cents, meant to be used like `wc_format_decimal` - * - * @param {number|string} number A floating point number (or integer), or string that converts to a number - * @return {number} The original number rounded to a decimal point - */ - formatDecimal( number ) { - if ( typeof number !== 'number' ) { - number = parseFloat( number ); - } - if ( Number.isNaN( number ) ) { - return 0; - } - return ( - Math.round( number * Math.pow( 10, this.precision ) ) / - Math.pow( 10, this.precision ) - ); - } - - /** - * Get the string representation of a floating point number to the precision used by the current currency. - * This is different from `formatCurrency` by not returning the currency symbol. - * - * @param {number|string} number A floating point number (or integer), or string that converts to a number - * @return {string} The original number rounded to a decimal point - */ - formatDecimalString( number ) { - if ( typeof number !== 'number' ) { - number = parseFloat( number ); - } - if ( Number.isNaN( number ) ) { - return ''; - } - return number.toFixed( this.precision ); - } - - /** - * Render a currency for display in a component. - * - * @param {number|string} number A floating point number (or integer), or string that converts to a number - * @return {Node|string} The number formatted as currency and rendered for display. - */ - render( number ) { - if ( typeof number !== 'number' ) { - number = parseFloat( number ); - } - if ( number < 0 ) { + /** + * Get the rounded decimal value of a number at the precision used for the current currency. + * This is a work-around for fraction-cents, meant to be used like `wc_format_decimal` + * + * @param {number|string} number A floating point number (or integer), or string that converts to a number + * @return {number} The original number rounded to a decimal point + */ + formatDecimal( number ) { + if ( typeof number !== 'number' ) { + number = parseFloat( number ); + } + if ( Number.isNaN( number ) ) { + return 0; + } + const { precision } = currency; return ( - - { this.formatCurrency( number ) } - + Math.round( number * Math.pow( 10, precision ) ) / + Math.pow( 10, precision ) ); - } - return this.formatCurrency( number ); - } -} + }, + + /** + * Get the string representation of a floating point number to the precision used by the current currency. + * This is different from `formatCurrency` by not returning the currency symbol. + * + * @param {number|string} number A floating point number (or integer), or string that converts to a number + * @return {string} The original number rounded to a decimal point + */ + formatDecimalString( number ) { + if ( typeof number !== 'number' ) { + number = parseFloat( number ); + } + if ( Number.isNaN( number ) ) { + return ''; + } + const { precision } = currency; + return number.toFixed( precision ); + }, + + /** + * Render a currency for display in a component. + * + * @param {number|string} number A floating point number (or integer), or string that converts to a number + * @return {Node|string} The number formatted as currency and rendered for display. + */ + render( number ) { + if ( typeof number !== 'number' ) { + number = parseFloat( number ); + } + if ( number < 0 ) { + return ( + + { formatCurrency( number ) } + + ); + } + return formatCurrency( number ); + }, + }; +}; + +export default Currency; /** * Returns currency data by country/region. Contains code, symbol, position, thousands separator, decimal separator, and precision. diff --git a/plugins/woocommerce-admin/packages/number/src/index.js b/plugins/woocommerce-admin/packages/number/src/index.js index 92fe5a34285..7865aec015d 100644 --- a/plugins/woocommerce-admin/packages/number/src/index.js +++ b/plugins/woocommerce-admin/packages/number/src/index.js @@ -20,16 +20,16 @@ export function numberFormat( return ''; } - precision = parseInt( precision, 10 ); + let parsedPrecision = parseInt( precision, 10 ); - if ( isNaN( precision ) ) { + if ( isNaN( parsedPrecision ) ) { const [ , decimals ] = number.toString().split( '.' ); - precision = decimals ? decimals.length : 0; + parsedPrecision = decimals ? decimals.length : 0; } return numberFormatter( number, - precision, + parsedPrecision, decimalSeparator, thousandSeparator );