diff --git a/plugins/woocommerce-admin/client/analytics/report/get-reports.js b/plugins/woocommerce-admin/client/analytics/report/get-reports.js
index ec3a66b0f39..5b130ae03b2 100644
--- a/plugins/woocommerce-admin/client/analytics/report/get-reports.js
+++ b/plugins/woocommerce-admin/client/analytics/report/get-reports.js
@@ -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 );
diff --git a/plugins/woocommerce-admin/client/layout/controller.js b/plugins/woocommerce-admin/client/layout/controller.js
index 94eb7af3672..54f38352aa6 100644
--- a/plugins/woocommerce-admin/client/layout/controller.js
+++ b/plugins/woocommerce-admin/client/layout/controller.js
@@ -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',
} );
}
diff --git a/plugins/woocommerce-admin/client/layout/index.js b/plugins/woocommerce-admin/client/layout/index.js
index fb7acdbb198..faaad61fdf4 100644
--- a/plugins/woocommerce-admin/client/layout/index.js
+++ b/plugins/woocommerce-admin/client/layout/index.js
@@ -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' )
diff --git a/plugins/woocommerce-admin/client/layout/navigation.js b/plugins/woocommerce-admin/client/layout/navigation.js
new file mode 100644
index 00000000000..27f85ccd48f
--- /dev/null
+++ b/plugins/woocommerce-admin/client/layout/navigation.js
@@ -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 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 ) => (
+
+
+ { page.breadcrumbs[ page.breadcrumbs.length - 1 ] }
+
+
+ ) ) }
+ { reports.map( ( item ) => (
+
+
+ { item.title }
+
+
+ ) ) }
+ >
+ );
+};
+
+registerPlugin( 'wc-admin-navigation', { render: NavigationPlugin } );
diff --git a/plugins/woocommerce-admin/client/navigation/components/Item/index.js b/plugins/woocommerce-admin/client/navigation/components/Item/index.js
index 1b5ec27ea30..68dca0676e7 100644
--- a/plugins/woocommerce-admin/client/navigation/components/Item/index.js
+++ b/plugins/woocommerce-admin/client/navigation/components/Item/index.js
@@ -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 ;
+ return (
+
+
+
+ );
}
+
return (
(
-
+
-
+
);
const HydratedNavigation = withNavigationHydration( window.wcNavigation )(
diff --git a/plugins/woocommerce-admin/packages/navigation/src/index.js b/plugins/woocommerce-admin/packages/navigation/src/index.js
index 25c8c3c4526..46c0ab3f2f3 100644
--- a/plugins/woocommerce-admin/packages/navigation/src/index.js
+++ b/plugins/woocommerce-admin/packages/navigation/src/index.js
@@ -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 (
-
-
- { children }
-
-
- );
+/**
+ * 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 { children };
};
-WooNavigationItem.Slot = ( { name } ) => ;
+WooNavigationItem.Slot = ( { 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 } ) => (
+ { children }
+);
+
+/**
+ * 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 );
diff --git a/plugins/woocommerce-admin/src/Features/Navigation/Navigation.php~HEAD b/plugins/woocommerce-admin/src/Features/Navigation/Navigation.php~HEAD
deleted file mode 100644
index d4d944d0ce8..00000000000
--- a/plugins/woocommerce-admin/src/Features/Navigation/Navigation.php~HEAD
+++ /dev/null
@@ -1,72 +0,0 @@
-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;
- }
-
- ?>
-
-