[Settings] Implement URL routing with query parameters and active sidebar item (#52721)
* set up SidebarNavigationScreen
* install deps
* GlobalStylesProvider
* Add labels to pages/sections
* get types in order
* get SettingItem working
* tidy up
* pass icon from PHP
* add icons to each Page
* layout styles
* edit site styles
* organize
* edit-site to 6.10
* unit tests
* lint
* lint
* Add changefile(s) from automation for the following project(s): @woocommerce/settings-editor, woocommerce, woocommerce/client/admin
* lint
* better linting
* [Settings] Create a route file to handle populating Settings (#52692)
* Add settings route
* Add changelog
* Add TODO comment
* Add changelog
* Rebase on sidebar changes
* Fix types and tests
* Fix path
* Convert to tab
* Update test
* Update sidebar to reflect the route with the active item and linking
* Add changelog
* Add changelog
* fix merge conflict errors
* Revert pnpm-lock.yaml
* [Settings] Update Modern Routes (#52757)
* update Sidebar
* cleanup
* Add changefile(s) from automation for the following project(s): @woocommerce/settings-editor
* export sidebar
* export route methods
* Revert "export route methods"
This reverts commit 46a6cd1e0a
.
* handle modern pages
* Add changefile(s) from automation for the following project(s): @woocommerce/settings-editor, woocommerce
* cleanup
* remove export
* update tests
---------
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
---------
Co-authored-by: paul sealock <psealock@gmail.com>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
parent
a518c49517
commit
295a2d83e2
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: tweak
|
||||
Comment: Organizes unreleased component
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: update
|
||||
|
||||
Update sidebar to reflect the route with the active item and linking
|
|
@ -16,8 +16,6 @@ import {
|
|||
} from '@wordpress/hooks';
|
||||
/* eslint-disable @woocommerce/dependency-group */
|
||||
// @ts-ignore No types for this exist yet.
|
||||
import SidebarNavigationScreen from '@wordpress/edit-site/build-module/components/sidebar-navigation-screen';
|
||||
// @ts-ignore No types for this exist yet.
|
||||
import { privateApis as routerPrivateApis } from '@wordpress/router';
|
||||
// @ts-ignore No types for this exist yet.
|
||||
import { unlock } from '@wordpress/edit-site/build-module/lock-unlock';
|
||||
|
@ -32,21 +30,29 @@ import { Route, Location } from './types';
|
|||
const { useLocation } = unlock( routerPrivateApis );
|
||||
|
||||
const NotFound = () => {
|
||||
return (
|
||||
<h1 style={ { color: 'white' } }>
|
||||
{ __( 'Page not found', 'woocommerce' ) }
|
||||
</h1>
|
||||
);
|
||||
return <h1>{ __( 'Page not found', 'woocommerce' ) }</h1>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Default route when a page is not found.
|
||||
* Default route when active page is not found.
|
||||
*
|
||||
* @param {string} activePage - The active page.
|
||||
* @param {typeof window.wcSettings.admin.settingsPages} pages - The pages.
|
||||
*
|
||||
*/
|
||||
const getNotFoundRoute = ( page: string ): Route => ( {
|
||||
key: page,
|
||||
const getNotFoundRoute = (
|
||||
activePage: string,
|
||||
pages: typeof window.wcSettings.admin.settingsPages
|
||||
): Route => ( {
|
||||
key: activePage,
|
||||
areas: {
|
||||
sidebar: null,
|
||||
sidebar: (
|
||||
<Sidebar
|
||||
activePage={ activePage }
|
||||
pages={ pages }
|
||||
pageTitle={ 'Settings' }
|
||||
/>
|
||||
),
|
||||
content: <NotFound />,
|
||||
edit: null,
|
||||
},
|
||||
|
@ -59,29 +65,35 @@ const getNotFoundRoute = ( page: string ): Route => ( {
|
|||
/**
|
||||
* Creates a route configuration for legacy settings pages.
|
||||
*
|
||||
* @param {string} page - The page identifier.
|
||||
* @param {string} activePage - The active page.
|
||||
* @param {typeof window.wcSettings.admin.settingsPages} pages - The pages.
|
||||
*/
|
||||
const getLegacyRoute = (
|
||||
page: string,
|
||||
activePage: string,
|
||||
pages: typeof window.wcSettings.admin.settingsPages
|
||||
): Route => ( {
|
||||
key: page,
|
||||
areas: {
|
||||
sidebar: (
|
||||
<SidebarNavigationScreen
|
||||
title={ 'Settings Title TBD' }
|
||||
isRoot
|
||||
content={ <Sidebar pages={ pages } /> }
|
||||
/>
|
||||
),
|
||||
content: <div>Content Placeholder: current tab: { page }</div>,
|
||||
edit: null,
|
||||
},
|
||||
widths: {
|
||||
content: undefined,
|
||||
edit: undefined,
|
||||
},
|
||||
} );
|
||||
): Route => {
|
||||
const pageTitle =
|
||||
pages[ activePage ]?.label || __( 'Settings', 'woocommerce' );
|
||||
|
||||
return {
|
||||
key: activePage,
|
||||
areas: {
|
||||
sidebar: (
|
||||
<Sidebar
|
||||
activePage={ activePage }
|
||||
pages={ pages }
|
||||
pageTitle={ pageTitle }
|
||||
/>
|
||||
),
|
||||
content: <div>Content Placeholder</div>,
|
||||
edit: null,
|
||||
},
|
||||
widths: {
|
||||
content: undefined,
|
||||
edit: undefined,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const PAGES_FILTER = 'woocommerce_admin_settings_pages';
|
||||
|
||||
|
@ -139,19 +151,36 @@ export const useActiveRoute = () => {
|
|||
const modernRoutes = useModernRoutes();
|
||||
|
||||
return useMemo( () => {
|
||||
const { tab: page = 'general' } = location.params;
|
||||
const pageSettings = settingsPages?.[ page ];
|
||||
const { tab: activePage = 'general' } = location.params;
|
||||
const pageSettings = settingsPages?.[ activePage ];
|
||||
|
||||
if ( ! pageSettings ) {
|
||||
return getNotFoundRoute( page );
|
||||
return getNotFoundRoute( activePage, settingsPages );
|
||||
}
|
||||
|
||||
// Handle legacy pages.
|
||||
if ( ! pageSettings.is_modern ) {
|
||||
return getLegacyRoute( page, settingsPages );
|
||||
return getLegacyRoute( activePage, settingsPages );
|
||||
}
|
||||
|
||||
const modernRoute = modernRoutes[ activePage ];
|
||||
|
||||
// Handle modern pages.
|
||||
return modernRoutes[ page ] || getNotFoundRoute( page );
|
||||
}, [ settingsPages, location, modernRoutes ] );
|
||||
if ( ! modernRoute ) {
|
||||
return getNotFoundRoute( activePage, settingsPages );
|
||||
}
|
||||
|
||||
// Sidebar is responsibility of WooCommerce, not extensions so add it here.
|
||||
modernRoute.areas.sidebar = (
|
||||
<Sidebar
|
||||
activePage={ activePage }
|
||||
pages={ settingsPages }
|
||||
pageTitle={ pageSettings.label }
|
||||
/>
|
||||
);
|
||||
// Make sure we have a key.
|
||||
modernRoute.key = activePage;
|
||||
|
||||
return modernRoute;
|
||||
}, [ settingsPages, location.params, modernRoutes ] );
|
||||
};
|
||||
|
|
|
@ -6,6 +6,8 @@ import { createElement } from '@wordpress/element';
|
|||
// @ts-expect-error missing type.
|
||||
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
|
||||
import { __experimentalItemGroup as ItemGroup } from '@wordpress/components';
|
||||
// @ts-ignore No types for this exist yet.
|
||||
import SidebarNavigationScreen from '@wordpress/edit-site/build-module/components/sidebar-navigation-screen';
|
||||
import * as IconPackage from '@wordpress/icons';
|
||||
/* eslint-enable @woocommerce/dependency-group */
|
||||
|
||||
|
@ -16,9 +18,11 @@ import { SettingItem } from './setting-item';
|
|||
|
||||
const { Icon, ...icons } = IconPackage;
|
||||
|
||||
export const Sidebar = ( {
|
||||
const SidebarNavigationScreenContent = ( {
|
||||
activePage,
|
||||
pages,
|
||||
}: {
|
||||
activePage: string;
|
||||
pages: typeof window.wcSettings.admin.settingsPages;
|
||||
} ) => {
|
||||
return (
|
||||
|
@ -30,7 +34,7 @@ export const Sidebar = ( {
|
|||
key={ slug }
|
||||
slug={ slug }
|
||||
label={ label }
|
||||
isActive={ false }
|
||||
isActive={ activePage === slug }
|
||||
icon={
|
||||
<Icon
|
||||
icon={
|
||||
|
@ -45,3 +49,26 @@ export const Sidebar = ( {
|
|||
</ItemGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const Sidebar = ( {
|
||||
activePage,
|
||||
pages,
|
||||
pageTitle,
|
||||
}: {
|
||||
activePage: string;
|
||||
pages: typeof window.wcSettings.admin.settingsPages;
|
||||
pageTitle: string;
|
||||
} ) => {
|
||||
return (
|
||||
<SidebarNavigationScreen
|
||||
title={ pageTitle }
|
||||
isRoot
|
||||
content={
|
||||
<SidebarNavigationScreenContent
|
||||
activePage={ activePage }
|
||||
pages={ pages }
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -63,11 +63,12 @@ export function SettingItem( {
|
|||
params: { postType, page },
|
||||
} = useLocation();
|
||||
|
||||
const linkInfo = useLink( {
|
||||
const { href, onClick } = useLink( {
|
||||
page,
|
||||
postType,
|
||||
slug,
|
||||
tab: slug,
|
||||
} );
|
||||
|
||||
return (
|
||||
<HStack
|
||||
justify="flex-start"
|
||||
|
@ -77,7 +78,8 @@ export function SettingItem( {
|
|||
>
|
||||
<SidebarNavigationItem
|
||||
icon={ icon }
|
||||
{ ...linkInfo }
|
||||
href={ href }
|
||||
onClick={ onClick }
|
||||
aria-current={ isActive ? 'true' : undefined }
|
||||
>
|
||||
{ label }
|
||||
|
|
|
@ -33,19 +33,11 @@ jest.mock( '@wordpress/edit-site/build-module/lock-unlock', () => ( {
|
|||
unlock: jest.fn( ( apis ) => apis ),
|
||||
} ) );
|
||||
|
||||
jest.mock(
|
||||
'@wordpress/edit-site/build-module/components/sidebar-navigation-screen',
|
||||
() => ( {
|
||||
__esModule: true,
|
||||
default: ( { children }: { children: React.ReactNode } ) => (
|
||||
<div data-testid="sidebar-navigation-screen">{ children }</div>
|
||||
),
|
||||
} )
|
||||
);
|
||||
|
||||
jest.mock( '../sidebar', () => ( {
|
||||
__esModule: true,
|
||||
Sidebar: jest.fn(),
|
||||
Sidebar: ( { children }: { children: React.ReactNode } ) => (
|
||||
<div data-testid="sidebar-navigation-screen">{ children }</div>
|
||||
),
|
||||
} ) );
|
||||
|
||||
const mockSettingsPages = {
|
||||
|
@ -141,11 +133,11 @@ describe( 'route.tsx', () => {
|
|||
admin: {
|
||||
settingsPages: {
|
||||
modern: {
|
||||
is_modern: true,
|
||||
label: 'Modern',
|
||||
icon: 'published',
|
||||
slug: 'modern',
|
||||
icon: 'settings',
|
||||
sections: [],
|
||||
is_modern: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -153,9 +145,7 @@ describe( 'route.tsx', () => {
|
|||
|
||||
( applyFilters as jest.Mock ).mockReturnValue( {
|
||||
modern: {
|
||||
key: 'modern',
|
||||
areas: {
|
||||
sidebar: null,
|
||||
content: <div>Modern Page</div>,
|
||||
},
|
||||
},
|
||||
|
@ -163,6 +153,7 @@ describe( 'route.tsx', () => {
|
|||
|
||||
const { result } = renderHook( () => useActiveRoute() );
|
||||
expect( result.current.key ).toBe( 'modern' );
|
||||
expect( result.current.areas.sidebar ).toBeDefined();
|
||||
} );
|
||||
} );
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: tweak
|
||||
Comment: Organizes unreleased component
|
||||
|
|
@ -38,6 +38,13 @@ if ( ! class_exists( 'WC_Settings_Page', false ) ) :
|
|||
*/
|
||||
protected $label = '';
|
||||
|
||||
/**
|
||||
* Setting page is modern.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $is_modern = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
|
@ -130,10 +137,11 @@ if ( ! class_exists( 'WC_Settings_Page', false ) ) :
|
|||
}
|
||||
|
||||
$pages[ $this->id ] = array(
|
||||
'label' => html_entity_decode( $this->label ),
|
||||
'slug' => $this->id,
|
||||
'icon' => $this->icon,
|
||||
'sections' => $sections_data,
|
||||
'label' => html_entity_decode( $this->label ),
|
||||
'slug' => $this->id,
|
||||
'icon' => $this->icon,
|
||||
'sections' => $sections_data,
|
||||
'is_modern' => $this->is_modern,
|
||||
);
|
||||
|
||||
return $pages;
|
||||
|
|
Loading…
Reference in New Issue