Navigation: extend with WC Admin router links (https://github.com/woocommerce/woocommerce-admin/pull/5445)
* add test case * save * pages * comments * use id * bail on no wcAdmin pages * prefix
This commit is contained in:
parent
29f6bcc126
commit
7e351c18a3
|
@ -57,58 +57,63 @@ export default () => {
|
|||
report: 'revenue',
|
||||
title: __( 'Revenue', 'woocommerce-admin' ),
|
||||
component: RevenueReport,
|
||||
id: 'woocommerce-analytics-revenue',
|
||||
},
|
||||
{
|
||||
report: 'products',
|
||||
title: __( 'Products', 'woocommerce-admin' ),
|
||||
component: ProductsReport,
|
||||
id: 'woocommerce-analytics-products',
|
||||
},
|
||||
{
|
||||
report: 'variations',
|
||||
title: __( 'Variations', 'woocommerce-admin' ),
|
||||
component: VariationsReport,
|
||||
id: 'woocommerce-analytics-variations',
|
||||
},
|
||||
{
|
||||
report: 'orders',
|
||||
title: __( 'Orders', 'woocommerce-admin' ),
|
||||
component: OrdersReport,
|
||||
id: 'woocommerce-analytics-orders',
|
||||
},
|
||||
{
|
||||
report: 'categories',
|
||||
title: __( 'Categories', 'woocommerce-admin' ),
|
||||
component: CategoriesReport,
|
||||
id: 'woocommerce-analytics-categories',
|
||||
},
|
||||
{
|
||||
report: 'coupons',
|
||||
title: __( 'Coupons', 'woocommerce-admin' ),
|
||||
component: CouponsReport,
|
||||
id: 'woocommerce-analytics-coupons',
|
||||
},
|
||||
{
|
||||
report: 'taxes',
|
||||
title: __( 'Taxes', 'woocommerce-admin' ),
|
||||
component: TaxesReport,
|
||||
},
|
||||
{
|
||||
report: 'downloads',
|
||||
title: __( 'Downloads', 'woocommerce-admin' ),
|
||||
component: DownloadsReport,
|
||||
id: 'woocommerce-analytics-taxes',
|
||||
},
|
||||
manageStock === 'yes'
|
||||
? {
|
||||
report: 'stock',
|
||||
title: __( 'Stock', 'woocommerce-admin' ),
|
||||
component: StockReport,
|
||||
id: 'woocommerce-analytics-stock',
|
||||
}
|
||||
: null,
|
||||
{
|
||||
report: 'customers',
|
||||
title: __( 'Customers', 'woocommerce-admin' ),
|
||||
component: CustomersReport,
|
||||
id: 'woocommerce-analytics-customers',
|
||||
},
|
||||
{
|
||||
report: 'downloads',
|
||||
title: __( 'Downloads', 'woocommerce-admin' ),
|
||||
component: DownloadsReport,
|
||||
id: 'woocommerce-analytics-downloads',
|
||||
},
|
||||
].filter( Boolean );
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ export const getPages = () => {
|
|||
__( 'Home', 'woocommerce-admin' ),
|
||||
],
|
||||
wpOpenMenu: 'toplevel_page_woocommerce',
|
||||
id: 'woocommerce-home',
|
||||
} );
|
||||
|
||||
if ( window.wcAdminFeatures.analytics ) {
|
||||
|
@ -74,6 +75,7 @@ export const getPages = () => {
|
|||
__( 'Overview', 'woocommerce-admin' ),
|
||||
],
|
||||
wpOpenMenu: 'toplevel_page_wc-admin-path--analytics-overview',
|
||||
id: 'woocommerce-analytics-overview',
|
||||
} );
|
||||
pages.push( {
|
||||
container: AnalyticsSettings,
|
||||
|
@ -87,6 +89,7 @@ export const getPages = () => {
|
|||
__( 'Settings', 'woocommerce-admin' ),
|
||||
],
|
||||
wpOpenMenu: 'toplevel_page_wc-admin-path--analytics-overview',
|
||||
id: 'woocommerce-analytics-settings',
|
||||
} );
|
||||
pages.push( {
|
||||
container: AnalyticsReport,
|
||||
|
@ -96,6 +99,7 @@ export const getPages = () => {
|
|||
__( 'Customers', 'woocommerce-admin' ),
|
||||
],
|
||||
wpOpenMenu: 'toplevel_page_woocommerce',
|
||||
id: 'woocommerce-analytics-customers',
|
||||
} );
|
||||
pages.push( {
|
||||
container: AnalyticsReport,
|
||||
|
@ -130,6 +134,7 @@ export const getPages = () => {
|
|||
__( 'Overview', 'woocommerce-admin' ),
|
||||
],
|
||||
wpOpenMenu: 'toplevel_page_woocommerce-marketing',
|
||||
id: 'woocommerce-marketing',
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { Controller, getPages } from './controller';
|
|||
import { Header } from '../header';
|
||||
import Notices from './notices';
|
||||
import TransientNotices from './transient-notices';
|
||||
import './navigation';
|
||||
|
||||
const StoreAlerts = lazy( () =>
|
||||
import( /* webpackChunkName: "store-alerts" */ './store-alerts' )
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerPlugin } from '@wordpress/plugins';
|
||||
import {
|
||||
WooNavigationItem,
|
||||
getNewPath,
|
||||
getPersistedQuery,
|
||||
} from '@woocommerce/navigation';
|
||||
import { Link } from '@woocommerce/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import getReports from '../analytics/report/get-reports';
|
||||
import { getPages } from './controller';
|
||||
import { isWCAdmin } from '../dashboard/utils';
|
||||
|
||||
const NavigationPlugin = () => {
|
||||
/**
|
||||
* If the current page is embedded, stay with the default urls
|
||||
* provided by Navigation because the router isn't present to
|
||||
* respond to <Link /> component's manipulation of the url.
|
||||
*/
|
||||
if ( ! isWCAdmin( window.location.href ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const reports = getReports();
|
||||
const pages = getPages()
|
||||
.filter( ( page ) => page.id )
|
||||
.map( ( page ) => {
|
||||
if ( page.id === 'woocommerce-analytics-settings' ) {
|
||||
return {
|
||||
...page,
|
||||
breadcrumbs: [ __( 'Analytics', 'woocommerce-admin' ) ],
|
||||
};
|
||||
}
|
||||
return page;
|
||||
} );
|
||||
const persistedQuery = getPersistedQuery( {} );
|
||||
return (
|
||||
<>
|
||||
{ pages.map( ( page ) => (
|
||||
<WooNavigationItem item={ page.id } key={ page.id }>
|
||||
<Link
|
||||
className="components-button"
|
||||
href={ getNewPath( persistedQuery, page.path, {} ) }
|
||||
type="wc-admin"
|
||||
>
|
||||
{ page.breadcrumbs[ page.breadcrumbs.length - 1 ] }
|
||||
</Link>
|
||||
</WooNavigationItem>
|
||||
) ) }
|
||||
{ reports.map( ( item ) => (
|
||||
<WooNavigationItem item={ item.id } key={ item.report }>
|
||||
<Link
|
||||
className="components-button"
|
||||
href={ getNewPath(
|
||||
persistedQuery,
|
||||
`/analytics/${ item.report }`,
|
||||
{}
|
||||
) }
|
||||
type="wc-admin"
|
||||
>
|
||||
{ item.title }
|
||||
</Link>
|
||||
</WooNavigationItem>
|
||||
) ) }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
registerPlugin( 'wc-admin-navigation', { render: NavigationPlugin } );
|
|
@ -1,20 +1,22 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
__experimentalNavigationItem as NavigationItem,
|
||||
__experimentalUseSlot as useSlot,
|
||||
} from '@wordpress/components';
|
||||
import { WooNavigationItem } from '@woocommerce/navigation';
|
||||
import { __experimentalNavigationItem as NavigationItem } from '@wordpress/components';
|
||||
import { WooNavigationItem, useNavSlot } from '@woocommerce/navigation';
|
||||
|
||||
const Item = ( { item } ) => {
|
||||
const slot = useSlot( item.id );
|
||||
const slot = useNavSlot( 'woocommerce_navigation_' + item.id );
|
||||
const hasFills = Boolean( slot.fills && slot.fills.length );
|
||||
|
||||
// Only render a slot if a coresponding Fill exists and the item is not a category
|
||||
if ( hasFills && ! item.isCategory ) {
|
||||
return <WooNavigationItem.Slot name={ item.id } />;
|
||||
return (
|
||||
<NavigationItem key={ item.id } item={ item.id }>
|
||||
<WooNavigationItem.Slot name={ item.id } />
|
||||
</NavigationItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<NavigationItem
|
||||
key={ item.id }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { SlotFillProvider } from '@wordpress/components';
|
||||
import { PluginArea } from '@wordpress/plugins';
|
||||
import { NavSlotFillProvider } from '@woocommerce/navigation';
|
||||
import { withNavigationHydration } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
|
@ -12,10 +12,10 @@ import './stylesheets/index.scss';
|
|||
import Container from './components/container';
|
||||
|
||||
const Navigation = () => (
|
||||
<SlotFillProvider>
|
||||
<NavSlotFillProvider>
|
||||
<Container />
|
||||
<PluginArea />
|
||||
</SlotFillProvider>
|
||||
</NavSlotFillProvider>
|
||||
);
|
||||
|
||||
const HydratedNavigation = withNavigationHydration( window.wcNavigation )(
|
||||
|
|
|
@ -6,9 +6,10 @@ import { parse } from 'qs';
|
|||
import { pick, uniq } from 'lodash';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import {
|
||||
__experimentalNavigationItem as NavigationItem,
|
||||
Slot,
|
||||
Fill,
|
||||
SlotFillProvider,
|
||||
__experimentalUseSlot as useSlot,
|
||||
} from '@wordpress/components';
|
||||
|
||||
/**
|
||||
|
@ -170,13 +171,42 @@ export function updateQueryString(
|
|||
getHistory().push( newPath );
|
||||
}
|
||||
|
||||
export const WooNavigationItem = ( { children, item, ...passProps } ) => {
|
||||
return (
|
||||
<Fill name={ item }>
|
||||
<NavigationItem item={ item } { ...passProps }>
|
||||
{ children }
|
||||
</NavigationItem>
|
||||
</Fill>
|
||||
);
|
||||
/**
|
||||
* Create a Fill for extensions to add client facing custom Navigation Items.
|
||||
*
|
||||
* @param {Object} param0
|
||||
* @param {Array} param0.children - Node children.
|
||||
* @param {string} param0.item - Navigation item slug.
|
||||
*/
|
||||
export const WooNavigationItem = ( { children, item } ) => {
|
||||
return <Fill name={ 'woocommerce_navigation_' + item }>{ children }</Fill>;
|
||||
};
|
||||
WooNavigationItem.Slot = ( { name } ) => <Slot name={ name } />;
|
||||
WooNavigationItem.Slot = ( { name } ) => (
|
||||
<Slot name={ 'woocommerce_navigation_' + name } />
|
||||
);
|
||||
|
||||
/**
|
||||
* Export @wordpress/components SlotFillProvider so that Slots, Fills, and useSlot
|
||||
* have access to the same context.
|
||||
*
|
||||
* This is a workaround because components exported from this package do not have
|
||||
* the same `context` as those created in the /client folder. This problem is due
|
||||
* to WC Admin bundling @wordpress/components instead of enqueuing and using
|
||||
* wp.components from the window.
|
||||
*
|
||||
* @param {Object} param0
|
||||
* @param {Array} param0.children - Node children.
|
||||
*/
|
||||
export const NavSlotFillProvider = ( { children } ) => (
|
||||
<SlotFillProvider>{ children }</SlotFillProvider>
|
||||
);
|
||||
|
||||
/**
|
||||
* Similar to NavSlotFillProvider above, this is a workaround because components
|
||||
* exported from this package do not have the same `context` as those created
|
||||
* in the /client folder. This problem is due to WC Admin bundling @wordpress/components
|
||||
* instead of enqueuing and using wp.components from the window.
|
||||
*
|
||||
* @param {string} name - slot name.
|
||||
*/
|
||||
export const useNavSlot = ( name ) => useSlot( name );
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Navigation Experience
|
||||
*
|
||||
* @package Woocommerce Admin
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\Features;
|
||||
|
||||
use Automattic\WooCommerce\Admin\Loader;
|
||||
use Automattic\WooCommerce\Admin\Features\Navigation\Screen;
|
||||
use Automattic\WooCommerce\Admin\Features\Navigation\Menu;
|
||||
use Automattic\WooCommerce\Admin\Features\Navigation\CoreMenu;
|
||||
|
||||
/**
|
||||
* Contains logic for the Navigation
|
||||
*/
|
||||
class Navigation {
|
||||
/**
|
||||
* Hook into WooCommerce.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_filter( 'woocommerce_admin_preload_options', array( $this, 'preload_options' ) );
|
||||
add_filter( 'woocommerce_admin_features', array( $this, 'maybe_remove_nav_feature' ), 0 );
|
||||
|
||||
if ( Loader::is_feature_enabled( 'navigation' ) ) {
|
||||
add_action( 'in_admin_header', array( __CLASS__, 'embed_navigation' ) );
|
||||
|
||||
Menu::instance()->init();
|
||||
CoreMenu::instance()->init();
|
||||
Screen::instance()->init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the allowed features array using a local `feature-config.php` file.
|
||||
*
|
||||
* @param array $features Array of feature slugs.
|
||||
*/
|
||||
public function maybe_remove_nav_feature( $features ) {
|
||||
if ( in_array( 'navigation', $features, true ) && 'yes' !== get_option( 'woocommerce_navigation_enabled', 'no' ) ) {
|
||||
$features = array_diff( $features, array( 'navigation' ) );
|
||||
}
|
||||
return $features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preload options to prime state of the application.
|
||||
*
|
||||
* @param array $options Array of options to preload.
|
||||
* @return array
|
||||
*/
|
||||
public function preload_options( $options ) {
|
||||
$options[] = 'woocommerce_navigation_enabled';
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up a div for the navigation.
|
||||
* The initial contents here are meant as a place loader for when the PHP page initialy loads.
|
||||
*/
|
||||
public static function embed_navigation() {
|
||||
if ( ! Screen::is_woocommerce_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="woocommerce-embedded-navigation"></div>
|
||||
<?php
|
||||
}
|
||||
}
|
|
@ -451,6 +451,7 @@ class Loader {
|
|||
'wp-date',
|
||||
'wp-plugins',
|
||||
'wc-tracks',
|
||||
'wc-navigation',
|
||||
),
|
||||
$js_file_version,
|
||||
true
|
||||
|
|
Loading…
Reference in New Issue