diff --git a/plugins/woocommerce-admin/client/analytics/index.js b/plugins/woocommerce-admin/client/analytics/index.js
new file mode 100644
index 00000000000..9f46de400f8
--- /dev/null
+++ b/plugins/woocommerce-admin/client/analytics/index.js
@@ -0,0 +1,21 @@
+/** @format */
+/**
+ * External dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { Component, Fragment } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import Header from 'components/header';
+
+export default class extends Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+}
diff --git a/plugins/woocommerce-admin/client/analytics/report/index.js b/plugins/woocommerce-admin/client/analytics/report/index.js
new file mode 100644
index 00000000000..4e4b1bd9b38
--- /dev/null
+++ b/plugins/woocommerce-admin/client/analytics/report/index.js
@@ -0,0 +1,28 @@
+/** @format */
+/**
+ * External dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import { Component, Fragment } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import Header from 'components/header';
+import { getAdminLink } from 'lib/nav-utils';
+
+export default class extends Component {
+ render() {
+ return (
+
+
+ );
+ }
+}
diff --git a/plugins/woocommerce-admin/client/components/header/index.js b/plugins/woocommerce-admin/client/components/header/index.js
index 8703590993f..b20ee2416bd 100644
--- a/plugins/woocommerce-admin/client/components/header/index.js
+++ b/plugins/woocommerce-admin/client/components/header/index.js
@@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
* Internal dependencies
*/
import './style.scss';
-import { getAdminLink } from '../../lib/nav-utils';
+import { getAdminLink } from 'lib/nav-utils';
// TODO Implement timeline icon
@@ -20,7 +20,7 @@ const Header = ( { sections, showTimeline } ) => {
return (
diff --git a/plugins/woocommerce-admin/client/index.js b/plugins/woocommerce-admin/client/index.js
index df4b6ddda86..3f2ed05c931 100644
--- a/plugins/woocommerce-admin/client/index.js
+++ b/plugins/woocommerce-admin/client/index.js
@@ -2,25 +2,86 @@
/**
* External dependencies
*/
-import { APIProvider } from '@wordpress/components';
-import { createElement, render } from '@wordpress/element';
import { addFilter } from '@wordpress/hooks';
-import { pick } from 'lodash';
+import { APIProvider } from '@wordpress/components';
+import { Component, createElement, render } from '@wordpress/element';
+import { HashRouter as Router, Route, Switch } from 'react-router-dom';
+import { parse } from 'qs';
+import { pick, find } from 'lodash';
/**
* Internal dependencies
*/
+import Analytics from './analytics';
+import AnalyticsReport from './analytics/report';
import Dashboard from './dashboard';
-render(
- createElement(
- APIProvider,
+const getPages = () => {
+ const pages = [
{
- ...wpApiSettings,
- ...pick( wp.api, [ 'postTypeRestBaseMapping', 'taxonomyRestBaseMapping' ] ),
+ container: Dashboard,
+ path: '/',
+ wpMenu: 'toplevel_page_woodash',
},
- createElement( Dashboard )
- ),
+ {
+ container: Analytics,
+ path: '/analytics',
+ wpMenu: 'toplevel_page_woodash--analytics',
+ },
+ {
+ container: AnalyticsReport,
+ path: '/analytics/:report',
+ wpMenu: 'toplevel_page_woodash--analytics',
+ },
+ ];
+
+ return pages;
+};
+
+class Controller extends Component {
+ render() {
+ // Pass URL parameters (example :report -> params.report) and query string parameters
+ const { path, params } = this.props.match;
+ const search = this.props.location.search.substring( 1 );
+ const query = parse( search );
+ const page = find( getPages(), { path } );
+ window.wpNavMenuClassChange( page.wpMenu );
+ return createElement( page.container, { params, query } );
+ }
+}
+
+// When the route changes, we need to update wp-admin's menu with the correct section & current link
+window.wpNavMenuClassChange = function( menuClass ) {
+ jQuery( '.current' ).each( function( i, obj ) {
+ jQuery( obj ).removeClass( 'current' );
+ } );
+ jQuery( '.wp-has-current-submenu' )
+ .removeClass( 'wp-has-current-submenu' )
+ .removeClass( 'wp-menu-open' )
+ .removeClass( 'selected' )
+ .addClass( 'wp-not-current-submenu menu-top' );
+ jQuery( 'li > a[href$="admin.php?page=woodash' + window.location.hash + '"]' )
+ .parent()
+ .addClass( 'current' );
+ jQuery( '#' + menuClass )
+ .removeClass( 'wp-not-current-submenu' )
+ .addClass( 'wp-has-current-submenu wp-menu-open current' );
+};
+
+render(
+
+
+
+ { getPages().map( page => {
+ return ;
+ } ) }
+
+
+
+ ,
document.getElementById( 'root' )
);
diff --git a/plugins/woocommerce-admin/client/lib/nav-utils.js b/plugins/woocommerce-admin/client/lib/nav-utils.js
index b477eb734c3..cfa05d7bea8 100644
--- a/plugins/woocommerce-admin/client/lib/nav-utils.js
+++ b/plugins/woocommerce-admin/client/lib/nav-utils.js
@@ -6,6 +6,6 @@
* @param {String} path Relative path.
* @return {String} Full admin URL.
*/
-export const getAdminLink = ( path ) => {
- return wcSettings.adminUrl + path;
+export const getAdminLink = path => {
+ return wcSettings.adminUrl + 'admin.php?page=woodash#' + path;
};
diff --git a/plugins/woocommerce-admin/lib/admin.php b/plugins/woocommerce-admin/lib/admin.php
index 7e9dc2e606e..5faf50ae2d3 100644
--- a/plugins/woocommerce-admin/lib/admin.php
+++ b/plugins/woocommerce-admin/lib/admin.php
@@ -12,9 +12,9 @@ function woo_dash_is_admin_page() {
}
/**
- * Register a new menu page for the Dashboard
+ * Register menu pages for the Dashboard and Analytics sections
*/
-function woo_dash_register_page(){
+function woo_dash_register_pages(){
// toplevel_page_woodash
add_menu_page(
__( 'Woo Dash', 'woo-dash' ),
@@ -25,8 +25,29 @@ function woo_dash_register_page(){
'dashicons-cart',
6
);
+
+ // toplevel_page_wooanalytics
+ add_menu_page(
+ __( 'WooCommerce Analytics', 'woo-dash' ),
+ __( 'WooAnalytics', 'woo-dash' ),
+ 'manage_options',
+ 'woodash#/analytics',
+ 'woo_dash_page',
+ 'dashicons-chart-bar',
+ 6
+ );
+
+ // TODO: Remove. Test report link
+ add_submenu_page(
+ 'woodash#/analytics',
+ __( 'Report Title', 'woo-dash' ),
+ __( 'Report Title', 'woo-dash' ),
+ 'manage_options',
+ 'woodash#/analytics/test',
+ 'woo_dash_page'
+ );
}
-add_action( 'admin_menu', 'woo_dash_register_page' );
+add_action( 'admin_menu', 'woo_dash_register_pages' );
/**
* Load the assets on the Dashboard page
diff --git a/plugins/woocommerce-admin/lib/client-assets.php b/plugins/woocommerce-admin/lib/client-assets.php
index e13638e72ee..9564a3fce9c 100644
--- a/plugins/woocommerce-admin/lib/client-assets.php
+++ b/plugins/woocommerce-admin/lib/client-assets.php
@@ -33,7 +33,8 @@ function woo_dash_register_script() {
);
wp_add_inline_script(
WOO_DASH_APP,
- 'var wcSettings = '. json_encode( $settings ) . ';',
+ 'var wcSettings = '. json_encode( $settings ) . ';' .
+ "jQuery( '#toplevel_page_woodash a' ).attr( 'href', 'admin.php?page=woodash#/' );",
'before'
);
}
diff --git a/plugins/woocommerce-admin/package-lock.json b/plugins/woocommerce-admin/package-lock.json
index bcc7a3cbd66..acdfb018c03 100644
--- a/plugins/woocommerce-admin/package-lock.json
+++ b/plugins/woocommerce-admin/package-lock.json
@@ -5451,6 +5451,12 @@
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
"dev": true
},
+ "hoist-non-react-statics": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz",
+ "integrity": "sha512-6Bl6XsDT1ntE0lHbIhr4Kp2PGcleGZ66qu5Jqk8lc0Xc/IeG6gVLmwUGs/K0Us+L8VWoKgj0uWdPMataOsm31w==",
+ "dev": true
+ },
"home-or-tmp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
@@ -8274,6 +8280,23 @@
"integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=",
"dev": true
},
+ "path-to-regexp": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+ "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+ "dev": true,
+ "requires": {
+ "isarray": "0.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ }
+ }
+ },
"path-type": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
@@ -9418,6 +9441,50 @@
"safe-buffer": "5.1.1"
}
},
+ "react-router-dom": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.2.2.tgz",
+ "integrity": "sha512-cHMFC1ZoLDfEaMFoKTjN7fry/oczMgRt5BKfMAkTu5zEuJvUiPp1J8d0eXSVTnBh6pxlbdqDhozunOOLtmKfPA==",
+ "dev": true,
+ "requires": {
+ "history": "4.7.2",
+ "invariant": "2.2.4",
+ "loose-envify": "1.3.1",
+ "prop-types": "15.6.1",
+ "react-router": "4.2.0",
+ "warning": "3.0.0"
+ },
+ "dependencies": {
+ "history": {
+ "version": "4.7.2",
+ "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz",
+ "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==",
+ "dev": true,
+ "requires": {
+ "invariant": "2.2.4",
+ "loose-envify": "1.3.1",
+ "resolve-pathname": "2.2.0",
+ "value-equal": "0.4.0",
+ "warning": "3.0.0"
+ }
+ },
+ "react-router": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz",
+ "integrity": "sha512-DY6pjwRhdARE4TDw7XjxjZsbx9lKmIcyZoZ+SDO7SBJ1KUeWNxT22Kara2AC7u6/c2SYEHlEDLnzBCcNhLE8Vg==",
+ "dev": true,
+ "requires": {
+ "history": "4.7.2",
+ "hoist-non-react-statics": "2.5.0",
+ "invariant": "2.2.4",
+ "loose-envify": "1.3.1",
+ "path-to-regexp": "1.7.0",
+ "prop-types": "15.6.1",
+ "warning": "3.0.0"
+ }
+ }
+ }
+ },
"read-chunk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz",
@@ -9813,6 +9880,12 @@
"integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
"dev": true
},
+ "resolve-pathname": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz",
+ "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==",
+ "dev": true
+ },
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -11398,6 +11471,12 @@
"spdx-expression-parse": "3.0.0"
}
},
+ "value-equal": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.4.0.tgz",
+ "integrity": "sha512-x+cYdNnaA3CxvMaTX0INdTCN8m8aF2uY9BvEqmxuYp8bL09cs/kWVQPVGcA35fMktdOsP69IgU7wFj/61dJHEw==",
+ "dev": true
+ },
"vendors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz",
@@ -11500,6 +11579,15 @@
"indexof": "0.0.1"
}
},
+ "warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
+ "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
+ "dev": true,
+ "requires": {
+ "loose-envify": "1.3.1"
+ }
+ },
"watchpack": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
diff --git a/plugins/woocommerce-admin/package.json b/plugins/woocommerce-admin/package.json
index d71c7f08ee9..209b64baaf6 100755
--- a/plugins/woocommerce-admin/package.json
+++ b/plugins/woocommerce-admin/package.json
@@ -44,6 +44,7 @@
"node-sass": "^4.9.0",
"prettier": "github:automattic/calypso-prettier#c56b4251",
"prop-types": "^15.6.1",
+ "react-router-dom": "^4.2.2",
"readline-sync": "^1.4.9",
"sass-loader": "^7.0.1",
"style-loader": "^0.21.0",