Homepage: Add stats overview selection (https://github.com/woocommerce/woocommerce-admin/pull/4264)
* Homwpage: add stats overview stat toggle * toggle stats * fix * tests * better hook name * clean up * add back in Fragment * remove extra prop * better test name
This commit is contained in:
parent
915ed69add
commit
3fc69b9739
|
@ -39,7 +39,7 @@ import { recordEvent } from 'lib/tracks';
|
|||
import { CurrencyContext } from 'lib/currency-context';
|
||||
|
||||
const { performanceIndicators: indicators } = getSetting( 'dataEndpoints', {
|
||||
performanceIndicators: '',
|
||||
performanceIndicators: [],
|
||||
} );
|
||||
|
||||
class StorePerformance extends Component {
|
||||
|
|
|
@ -14,6 +14,7 @@ import { Spinner } from '@woocommerce/components';
|
|||
*/
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { isOnboardingEnabled } from 'dashboard/utils';
|
||||
import StatsOverview from './stats-overview';
|
||||
|
||||
const ProfileWizard = lazy( () =>
|
||||
import( /* webpackChunkName: "profile-wizard" */ '../profile-wizard' )
|
||||
|
@ -28,7 +29,7 @@ const Homepage = ( { profileItems, query } ) => {
|
|||
);
|
||||
}
|
||||
|
||||
return <div>Hello World</div>;
|
||||
return <StatsOverview />;
|
||||
};
|
||||
|
||||
export default compose(
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
|
||||
export const DEFAULT_STATS = applyFilters(
|
||||
'woocommerce_admin_homepage_default_stats',
|
||||
[
|
||||
'revenue/total_sales',
|
||||
'revenue/net_revenue',
|
||||
'orders/orders_count',
|
||||
'products/items_sold',
|
||||
]
|
||||
);
|
||||
|
||||
export const DEFAULT_HIDDEN_STATS = [
|
||||
'revenue/net_revenue',
|
||||
'products/items_sold',
|
||||
];
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { Fragment } from '@wordpress/element';
|
||||
import { xor } from 'lodash';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import PropTypes from 'prop-types';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import {
|
||||
Card,
|
||||
EllipsisMenu,
|
||||
MenuItem,
|
||||
MenuTitle,
|
||||
} from '@woocommerce/components';
|
||||
import { getSetting } from '@woocommerce/wc-admin-settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { DEFAULT_STATS, DEFAULT_HIDDEN_STATS } from './defaults';
|
||||
|
||||
const { performanceIndicators } = getSetting( 'dataEndpoints', {
|
||||
performanceIndicators: [],
|
||||
} );
|
||||
const stats = performanceIndicators.filter( ( indicator ) => {
|
||||
return DEFAULT_STATS.includes( indicator.stat );
|
||||
} );
|
||||
|
||||
export const StatsOverview = ( { userPrefs, updateCurrentUserData } ) => {
|
||||
const userHiddenStats = userPrefs.hiddenStats;
|
||||
const hiddenStats = userHiddenStats
|
||||
? userHiddenStats
|
||||
: DEFAULT_HIDDEN_STATS;
|
||||
|
||||
const toggleStat = ( stat ) => {
|
||||
const nextHiddenStats = xor( hiddenStats, [ stat ] );
|
||||
updateCurrentUserData( {
|
||||
homepage_stats: { hiddenStats: nextHiddenStats },
|
||||
} );
|
||||
recordEvent( 'statsoverview_indicators_toggle', {
|
||||
indicator_name: stat,
|
||||
status: nextHiddenStats.includes( stat ) ? 'off' : 'on',
|
||||
} );
|
||||
};
|
||||
|
||||
return (
|
||||
<Card
|
||||
className="woocommerce-analytics__card"
|
||||
title={ __( 'Stats overview', 'woocommerce-admin' ) }
|
||||
menu={
|
||||
<EllipsisMenu
|
||||
label={ __(
|
||||
'Choose which values to display',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
renderContent={ () => (
|
||||
<Fragment>
|
||||
<MenuTitle>
|
||||
{ __( 'Display stats:', 'woocommerce-admin' ) }
|
||||
</MenuTitle>
|
||||
{ stats.map( ( item ) => {
|
||||
const checked = ! hiddenStats.includes(
|
||||
item.stat
|
||||
);
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
checked={ checked }
|
||||
isCheckbox
|
||||
isClickable
|
||||
key={ item.stat }
|
||||
onInvoke={ () =>
|
||||
toggleStat( item.stat )
|
||||
}
|
||||
>
|
||||
{ item.label }
|
||||
</MenuItem>
|
||||
);
|
||||
} ) }
|
||||
</Fragment>
|
||||
) }
|
||||
/>
|
||||
}
|
||||
>
|
||||
Content Here
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
StatsOverview.propTypes = {
|
||||
/**
|
||||
* Homepage user preferences.
|
||||
*/
|
||||
userPrefs: PropTypes.object.isRequired,
|
||||
/**
|
||||
* A method to update user meta.
|
||||
*/
|
||||
updateCurrentUserData: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getCurrentUserData } = select( 'wc-api' );
|
||||
|
||||
return {
|
||||
userPrefs: getCurrentUserData().homepage_stats || {},
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { updateCurrentUserData } = dispatch( 'wc-api' );
|
||||
|
||||
return {
|
||||
updateCurrentUserData,
|
||||
};
|
||||
} )
|
||||
)( StatsOverview );
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render, fireEvent, screen } from '@testing-library/react';
|
||||
import { StatsOverview } from '../index';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
|
||||
jest.mock( 'lib/tracks' );
|
||||
|
||||
describe( 'StatsOverview tracking', () => {
|
||||
it( 'should record an event when a stat is toggled', () => {
|
||||
render(
|
||||
<StatsOverview
|
||||
userPrefs={ {
|
||||
hiddenStats: null,
|
||||
} }
|
||||
updateCurrentUserData={ () => {} }
|
||||
/>
|
||||
);
|
||||
|
||||
const ellipsisBtn = screen.getByTitle(
|
||||
'Choose which values to display'
|
||||
);
|
||||
fireEvent.click( ellipsisBtn );
|
||||
const totalSalesBtn = screen.getByText( 'Total Sales' );
|
||||
fireEvent.click( totalSalesBtn );
|
||||
|
||||
expect( recordEvent ).toHaveBeenCalledWith(
|
||||
'statsoverview_indicators_toggle',
|
||||
{
|
||||
indicator_name: 'revenue/total_sales',
|
||||
status: 'off',
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'StatsOverview toggle and persist stat preference', () => {
|
||||
it( 'should update preferences', () => {
|
||||
const updateCurrentUserData = jest.fn();
|
||||
|
||||
render(
|
||||
<StatsOverview
|
||||
userPrefs={ {
|
||||
hiddenStats: null,
|
||||
} }
|
||||
updateCurrentUserData={ updateCurrentUserData }
|
||||
/>
|
||||
);
|
||||
|
||||
const ellipsisBtn = screen.getByTitle(
|
||||
'Choose which values to display'
|
||||
);
|
||||
fireEvent.click( ellipsisBtn );
|
||||
const totalSalesBtn = screen.getByText( 'Total Sales' );
|
||||
fireEvent.click( totalSalesBtn );
|
||||
|
||||
expect( updateCurrentUserData ).toHaveBeenCalledWith( {
|
||||
homepage_stats: {
|
||||
hiddenStats: [
|
||||
'revenue/net_revenue',
|
||||
'products/items_sold',
|
||||
'revenue/total_sales',
|
||||
],
|
||||
},
|
||||
} );
|
||||
} );
|
||||
} );
|
|
@ -1,15 +0,0 @@
|
|||
import { render } from '@testing-library/react';
|
||||
import Homepage from '../index';
|
||||
|
||||
describe( 'homepage', () => {
|
||||
it( 'should render', () => {
|
||||
const { container } = render( <Homepage /> );
|
||||
expect( container ).toMatchInlineSnapshot( `
|
||||
<div>
|
||||
<div>
|
||||
Hello World
|
||||
</div>
|
||||
</div>
|
||||
` );
|
||||
} );
|
||||
} );
|
|
@ -47,6 +47,7 @@ function updateCurrentUserData( resourceNames, data, fetch ) {
|
|||
'dashboard_chart_interval',
|
||||
'dashboard_leaderboard_rows',
|
||||
'activity_panel_inbox_last_read',
|
||||
'homepage_stats',
|
||||
];
|
||||
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
|
|
|
@ -71,6 +71,7 @@ class AnalyticsDashboard {
|
|||
'dashboard_chart_type',
|
||||
'dashboard_chart_interval',
|
||||
'dashboard_leaderboard_rows',
|
||||
'homepage_stats',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -80,8 +81,8 @@ class AnalyticsDashboard {
|
|||
*/
|
||||
public function register_page() {
|
||||
$features = wc_admin_get_feature_config();
|
||||
$id = $features['homepage'] ? 'woocommerce-home' : 'woocommerce-dashboard';
|
||||
$title = $features['homepage'] ? __( 'Home', 'woocommerce-admin' ) : __( 'Dashboard', 'woocommerce-admin' );
|
||||
$id = $features['homepage'] ? 'woocommerce-home' : 'woocommerce-dashboard';
|
||||
$title = $features['homepage'] ? __( 'Home', 'woocommerce-admin' ) : __( 'Dashboard', 'woocommerce-admin' );
|
||||
|
||||
wc_admin_register_page(
|
||||
array(
|
||||
|
|
|
@ -62,7 +62,30 @@ global.wcSettings = {
|
|||
woocommerce_actionable_order_statuses: [],
|
||||
woocommerce_excluded_report_order_statuses: [],
|
||||
},
|
||||
dataEndpoints: {},
|
||||
dataEndpoints: {
|
||||
performanceIndicators: [
|
||||
{
|
||||
chart: 'total_sales',
|
||||
label: 'Total Sales',
|
||||
stat: 'revenue/total_sales',
|
||||
},
|
||||
{
|
||||
chart: 'net_revenue',
|
||||
label: 'Net Sales',
|
||||
stat: 'revenue/net_revenue',
|
||||
},
|
||||
{
|
||||
chart: 'orders_count',
|
||||
label: 'Orders',
|
||||
stat: 'orders/orders_count',
|
||||
},
|
||||
{
|
||||
chart: 'items_sold',
|
||||
label: 'Items Sold',
|
||||
stat: 'products/items_sold',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
wordPressPackages.forEach( ( lib ) => {
|
||||
|
|
Loading…
Reference in New Issue