* getCategoriesMap

* getMenuItemsByCategory

* changelog
This commit is contained in:
Paul Sealock 2021-02-19 07:06:28 +13:00 committed by GitHub
parent 8371325ba6
commit 3483f1930e
4 changed files with 282 additions and 59 deletions

View File

@ -22,23 +22,22 @@ import CategoryTitle from '../category-title';
import Header from '../header';
import Item from '../../components/Item';
const Container = ( { menuItems } ) => {
useEffect( () => {
// Collapse the original WP Menu.
document.documentElement.classList.remove( 'wp-toolbar' );
document.body.classList.add( 'has-woocommerce-navigation' );
const adminMenu = document.getElementById( 'adminmenumain' );
if ( ! adminMenu ) {
return;
/**
* Get a map of all categories, including the topmost WooCommerce parentCategory
*
* @param {Array} menuItems Array of menuItems
* @return {Object} Map of categories by id
*/
export const getCategoriesMap = ( menuItems ) => {
return menuItems.reduce(
( acc, item ) => {
if ( item.isCategory ) {
return { ...acc, [ item.id ]: item };
}
adminMenu.classList.add( 'folded' );
}, [] );
const { rootBackLabel, rootBackUrl } = window.wcNavigation;
const parentCategory = {
return acc;
},
{
woocommerce: {
capability: 'manage_woocommerce',
id: 'woocommerce',
isCategory: true,
@ -47,44 +46,20 @@ const Container = ( { menuItems } ) => {
order: 10,
parent: '',
title: 'WooCommerce',
};
const categoriesMap = menuItems.reduce(
( acc, item ) => {
if ( item.isCategory ) {
return { ...acc, [ item.id ]: item };
}
return acc;
},
{
woocommerce: parentCategory,
}
);
const categories = Object.values( categoriesMap );
};
const [ activeItem, setActiveItem ] = useState( 'woocommerce-home' );
const [ activeLevel, setActiveLevel ] = useState( 'woocommerce' );
useEffect( () => {
const initialMatchedItem = getMatchingItem( menuItems );
if ( initialMatchedItem && activeItem !== initialMatchedItem ) {
setActiveItem( initialMatchedItem );
setActiveLevel( initialMatchedItem.parent );
}
const removeListener = addHistoryListener( () => {
setTimeout( () => {
const matchedItem = getMatchingItem( menuItems );
if ( matchedItem ) {
setActiveItem( matchedItem );
}
}, 0 );
} );
return removeListener;
}, [ menuItems ] );
const getMenuItemsByCategory = ( items ) => {
return items.reduce( ( acc, item ) => {
/**
* Get a flat tree structure of all Categories and thier children grouped by menuId
*
* @param {Object} categoriesMap Map of categories by id
* @param {Array} menuItems Array of menuItems
* @return {Object} a;dslkfj
*/
export const getMenuItemsByCategory = ( categoriesMap, menuItems ) => {
return menuItems.reduce( ( acc, item ) => {
// Set up the category if it doesn't yet exist.
if ( ! acc[ item.parent ] ) {
acc[ item.parent ] = {};
@ -111,9 +86,50 @@ const Container = ( { menuItems } ) => {
}, {} );
};
const Container = ( { menuItems } ) => {
useEffect( () => {
// Collapse the original WP Menu.
document.documentElement.classList.remove( 'wp-toolbar' );
document.body.classList.add( 'has-woocommerce-navigation' );
const adminMenu = document.getElementById( 'adminmenumain' );
if ( ! adminMenu ) {
return;
}
adminMenu.classList.add( 'folded' );
}, [] );
const { rootBackLabel, rootBackUrl } = window.wcNavigation;
const categoriesMap = getCategoriesMap( menuItems );
const categories = Object.values( categoriesMap );
const [ activeItem, setActiveItem ] = useState( 'woocommerce-home' );
const [ activeLevel, setActiveLevel ] = useState( 'woocommerce' );
useEffect( () => {
const initialMatchedItem = getMatchingItem( menuItems );
if ( initialMatchedItem && activeItem !== initialMatchedItem ) {
setActiveItem( initialMatchedItem );
setActiveLevel( initialMatchedItem.parent );
}
const removeListener = addHistoryListener( () => {
setTimeout( () => {
const matchedItem = getMatchingItem( menuItems );
if ( matchedItem ) {
setActiveItem( matchedItem );
}
}, 0 );
} );
return removeListener;
}, [ menuItems ] );
const categorizedItems = useMemo(
() => getMenuItemsByCategory( menuItems ),
[ menuItems ]
() => getMenuItemsByCategory( categoriesMap, menuItems ),
[ categoriesMap, menuItems ]
);
const navDomRef = useRef( null );

View File

@ -0,0 +1,204 @@
/**
* Internal dependencies
*/
import { getCategoriesMap, getMenuItemsByCategory } from '../';
describe( 'getCategoriesMap', () => {
const menuItems = [
{ id: 'zero', title: 'zero', isCategory: true },
{ id: 'one', title: 'one', isCategory: true },
{ id: 'two', title: 'two', isCategory: true },
{ id: 'three', title: 'three', isCategory: false },
{ id: 'four', title: 'four', isCategory: false },
];
it( 'should get a map of all categories', () => {
const categoriesMap = getCategoriesMap( menuItems );
expect( categoriesMap.zero ).toMatchObject( menuItems[ 0 ] );
expect( categoriesMap.one ).toMatchObject( menuItems[ 1 ] );
expect( categoriesMap.two ).toMatchObject( menuItems[ 2 ] );
expect( categoriesMap.three ).toBeUndefined();
expect( categoriesMap.four ).toBeUndefined();
} );
it( 'should include the topmost WooCommerce parent category', () => {
const categoriesMap = getCategoriesMap( menuItems );
expect( categoriesMap.woocommerce ).toBeDefined();
} );
it( 'should have the correct number of values', () => {
const categoriesMap = getCategoriesMap( menuItems );
expect( Object.keys( categoriesMap ).length ).toBe( 4 );
} );
} );
describe( 'getMenuItemsByCategory', () => {
it( 'should get a map of all categories and child elements', () => {
const menuItems = [
{
id: 'child-one',
title: 'child-one',
isCategory: false,
parent: 'parent',
menuId: 'plugins',
},
{
id: 'child-two',
title: 'child-two',
isCategory: false,
parent: 'parent',
menuId: 'plugins',
},
{
id: 'parent',
title: 'parent',
isCategory: true,
parent: 'woocommerce',
menuId: 'plugins',
},
];
const categoriesMap = getCategoriesMap( menuItems );
const categorizedItems = getMenuItemsByCategory(
categoriesMap,
menuItems
);
expect( categorizedItems.woocommerce ).toBeDefined();
expect( categorizedItems.woocommerce.plugins ).toBeDefined();
expect( categorizedItems.woocommerce.plugins.length ).toBe( 1 );
expect( categorizedItems.parent ).toBeDefined();
expect( categorizedItems.parent.plugins ).toBeDefined();
expect( categorizedItems.parent.plugins.length ).toBe( 2 );
} );
it( 'should handle multiple depths', () => {
const menuItems = [
{
id: 'grand-child',
title: 'grand-child',
isCategory: false,
parent: 'child',
menuId: 'plugins',
},
{
id: 'child',
title: 'child',
isCategory: true,
parent: 'grand-parent',
menuId: 'plugins',
},
{
id: 'grand-parent',
title: 'grand-parent',
isCategory: true,
parent: 'woocommerce',
menuId: 'plugins',
},
];
const categoriesMap = getCategoriesMap( menuItems );
const categorizedItems = getMenuItemsByCategory(
categoriesMap,
menuItems
);
expect( categorizedItems[ 'grand-parent' ] ).toBeDefined();
expect( categorizedItems[ 'grand-parent' ] ).toBeDefined();
expect( categorizedItems[ 'grand-parent' ].plugins.length ).toBe( 1 );
expect( categorizedItems.child ).toBeDefined();
expect( categorizedItems.child ).toBeDefined();
expect( categorizedItems.child.plugins.length ).toBe( 1 );
expect( categorizedItems[ 'grand-child' ] ).not.toBeDefined();
} );
it( 'should group by menuId', () => {
const menuItems = [
{
id: 'parent',
title: 'parent',
isCategory: true,
parent: 'woocommerce',
menuId: 'primary',
},
{
id: 'primary-one',
title: 'primary-one',
isCategory: false,
parent: 'parent',
menuId: 'primary',
},
{
id: 'primary-two',
title: 'primary-two',
isCategory: false,
parent: 'parent',
menuId: 'primary',
},
];
const categoriesMap = getCategoriesMap( menuItems );
const categorizedItems = getMenuItemsByCategory(
categoriesMap,
menuItems
);
expect( categorizedItems.parent ).toBeDefined();
expect( categorizedItems.parent.primary ).toBeDefined();
expect( categorizedItems.parent.primary.length ).toBe( 2 );
} );
it( 'should group children only if their menuId matches parent', () => {
const menuItems = [
{
id: 'plugin-one',
title: 'plugin-one',
isCategory: false,
parent: 'parent',
menuId: 'plugins',
},
{
id: 'plugin-two',
title: 'plugin-two',
isCategory: false,
parent: 'parent',
menuId: 'plugins',
},
{
id: 'parent',
title: 'parent',
isCategory: true,
parent: 'woocommerce',
menuId: 'plugins',
},
{
id: 'primary-one',
title: 'primary-one',
isCategory: false,
parent: 'parent',
menuId: 'primary',
},
{
id: 'primary-two',
title: 'primary-two',
isCategory: false,
parent: 'parent',
menuId: 'primary',
},
];
const categoriesMap = getCategoriesMap( menuItems );
const categorizedItems = getMenuItemsByCategory(
categoriesMap,
menuItems
);
expect( categorizedItems.parent ).toBeDefined();
expect( categorizedItems.parent.plugins ).toBeDefined();
expect( categorizedItems.parent.plugins.length ).toBe( 2 );
expect( categorizedItems.primary ).not.toBeDefined();
} );
} );

View File

@ -48,6 +48,7 @@
"config": "^3.2.4",
"eslint": "6.7.2",
"jest": "^24.9.0",
"prettier": "npm:wp-prettier@1.19.1",
"puppeteer": "^2.0.0"
},
"dependencies": {
@ -142,6 +143,11 @@
}
}
}
},
"prettier": {
"version": "npm:wp-prettier@1.19.1",
"resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-1.19.1.tgz",
"integrity": "sha512-mqAC2r1NDmRjG+z3KCJ/i61tycKlmADIjxnDhQab+KBxSAGbF/W7/zwB2guy/ypIeKrrftNsIYkNZZQKf3vJcg=="
}
}
},
@ -9049,8 +9055,7 @@
}
},
"@woocommerce/currency": {
"version": "3.0.0",
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/currency",
"version": "file:packages/currency",
"dev": true,
"requires": {
"@babel/runtime-corejs2": "7.12.5",
@ -9167,8 +9172,7 @@
}
},
"@woocommerce/data": {
"version": "1.1.1",
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/data",
"version": "file:packages/data",
"dev": true,
"requires": {
"@babel/runtime-corejs2": "7.12.5",
@ -9178,8 +9182,7 @@
}
},
"@woocommerce/date": {
"version": "2.1.0",
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/date",
"version": "file:packages/date",
"dev": true,
"requires": {
"@babel/runtime-corejs2": "7.12.5",
@ -10192,8 +10195,7 @@
}
},
"@woocommerce/navigation": {
"version": "5.2.0",
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/navigation",
"version": "file:packages/navigation",
"dev": true,
"requires": {
"lodash": "4.17.15"

View File

@ -78,6 +78,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
- Dev: Allow highlight tooltip to use body tag as parent. #6309
- Dev: Remove Google fonts and material icons. #6343
- Add: Remove CES actions for adding and editing a product and editing an order #6355
- Dev: Add unit tests to Navigation's Container component. #6344
== 2.0.0 02/05/2021 ==