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';
|
import { CurrencyContext } from 'lib/currency-context';
|
||||||
|
|
||||||
const { performanceIndicators: indicators } = getSetting( 'dataEndpoints', {
|
const { performanceIndicators: indicators } = getSetting( 'dataEndpoints', {
|
||||||
performanceIndicators: '',
|
performanceIndicators: [],
|
||||||
} );
|
} );
|
||||||
|
|
||||||
class StorePerformance extends Component {
|
class StorePerformance extends Component {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { Spinner } from '@woocommerce/components';
|
||||||
*/
|
*/
|
||||||
import withSelect from 'wc-api/with-select';
|
import withSelect from 'wc-api/with-select';
|
||||||
import { isOnboardingEnabled } from 'dashboard/utils';
|
import { isOnboardingEnabled } from 'dashboard/utils';
|
||||||
|
import StatsOverview from './stats-overview';
|
||||||
|
|
||||||
const ProfileWizard = lazy( () =>
|
const ProfileWizard = lazy( () =>
|
||||||
import( /* webpackChunkName: "profile-wizard" */ '../profile-wizard' )
|
import( /* webpackChunkName: "profile-wizard" */ '../profile-wizard' )
|
||||||
|
@ -28,7 +29,7 @@ const Homepage = ( { profileItems, query } ) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>Hello World</div>;
|
return <StatsOverview />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default compose(
|
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_chart_interval',
|
||||||
'dashboard_leaderboard_rows',
|
'dashboard_leaderboard_rows',
|
||||||
'activity_panel_inbox_last_read',
|
'activity_panel_inbox_last_read',
|
||||||
|
'homepage_stats',
|
||||||
];
|
];
|
||||||
|
|
||||||
if ( resourceNames.includes( resourceName ) ) {
|
if ( resourceNames.includes( resourceName ) ) {
|
||||||
|
|
|
@ -71,6 +71,7 @@ class AnalyticsDashboard {
|
||||||
'dashboard_chart_type',
|
'dashboard_chart_type',
|
||||||
'dashboard_chart_interval',
|
'dashboard_chart_interval',
|
||||||
'dashboard_leaderboard_rows',
|
'dashboard_leaderboard_rows',
|
||||||
|
'homepage_stats',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -80,8 +81,8 @@ class AnalyticsDashboard {
|
||||||
*/
|
*/
|
||||||
public function register_page() {
|
public function register_page() {
|
||||||
$features = wc_admin_get_feature_config();
|
$features = wc_admin_get_feature_config();
|
||||||
$id = $features['homepage'] ? 'woocommerce-home' : 'woocommerce-dashboard';
|
$id = $features['homepage'] ? 'woocommerce-home' : 'woocommerce-dashboard';
|
||||||
$title = $features['homepage'] ? __( 'Home', 'woocommerce-admin' ) : __( 'Dashboard', 'woocommerce-admin' );
|
$title = $features['homepage'] ? __( 'Home', 'woocommerce-admin' ) : __( 'Dashboard', 'woocommerce-admin' );
|
||||||
|
|
||||||
wc_admin_register_page(
|
wc_admin_register_page(
|
||||||
array(
|
array(
|
||||||
|
|
|
@ -62,7 +62,30 @@ global.wcSettings = {
|
||||||
woocommerce_actionable_order_statuses: [],
|
woocommerce_actionable_order_statuses: [],
|
||||||
woocommerce_excluded_report_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 ) => {
|
wordPressPackages.forEach( ( lib ) => {
|
||||||
|
|
Loading…
Reference in New Issue