diff --git a/projects/packages/my-jetpack/_inc/components/connection-screen/index.tsx b/projects/packages/my-jetpack/_inc/components/connection-screen/index.tsx index 9fb6f13fc70d..33a5377deab5 100644 --- a/projects/packages/my-jetpack/_inc/components/connection-screen/index.tsx +++ b/projects/packages/my-jetpack/_inc/components/connection-screen/index.tsx @@ -15,7 +15,7 @@ const ConnectionScreen: FC = () => { const returnToPage = useMyJetpackReturnToPage(); const { apiRoot, apiNonce, registrationNonce } = useMyJetpackConnection(); return ( - + feature.slug === openSlug ); - // Neither read has anything to say yet: a seed-only catalog is not a failure to load - // one, and features whose modules are still in flight all read inactive, which would - // otherwise announce "nothing is active" on a site with plenty on. - // Only the status filters wait on the modules: a search or a plan filter is already - // a settled answer once the catalog is here, and an unreachable module read would - // otherwise leave those two with no message at all. - const onStatus = filter === 'active' || filter === 'inactive'; + // Module-dependent filters cannot report no matches until their modules arrive. + const onModules = + filter === 'active' || filter === 'inactive' || ( filter === 'available' && ! search.trim() ); const settling = ( mainFeatures.isPlaceholderData && mainFeatures.features.length === 0 ) || - ( onStatus && states.some( state => state.pending ) ); + ( onModules && states.some( state => state.pending ) ); return (
diff --git a/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/content.test.tsx b/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/content.test.tsx index a5a633c0dbcb..ce078630a6cd 100644 --- a/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/content.test.tsx +++ b/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/content.test.tsx @@ -141,12 +141,32 @@ describe( 'FeaturesContent', () => { expect( screen.queryByRole( 'heading' ) ).not.toBeInTheDocument(); } ); - it( 'still answers a search that matched nothing while modules are in flight', () => { - mockStates = [ { ...activeStats, pending: true, status: 'inactive' } as FeatureState ]; + it.each( [ 'all', 'available' ] )( + 'still answers a search that matched nothing while modules are in flight (filter: %s)', + filter => { + mockStates = [ { ...activeStats, pending: true, status: 'inactive' } as FeatureState ]; + + renderAt( `/features?filter=${ filter }&search=zzzz` ); + + expect( screen.getByRole( 'heading' ) ).toHaveTextContent( 'No features match “zzzz”.' ); + } + ); + + it( 'waits for modules before reporting an empty Available filter after a reload', () => { + mockIsLoading = true; + mockStates = [ { ...activeStats, pending: true } as FeatureState ]; + const { rerenderAt } = renderAt( '/features?filter=available' ); - renderAt( '/features?search=zzzz' ); + expect( screen.queryByText( 'No features found.' ) ).not.toBeInTheDocument(); - expect( screen.getByRole( 'heading' ) ).toHaveTextContent( 'No features match “zzzz”.' ); + mockIsLoading = false; + mockStates = [ activeStats ]; + rerenderAt(); + expect( screen.getByText( 'grid card' ) ).toBeInTheDocument(); + + mockStates = [ { ...activeStats, unavailableReason: 'Unavailable' } ]; + rerenderAt(); + expect( screen.getByText( 'No features found.' ) ).toBeInTheDocument(); } ); it( 'reports an empty catalog as a failure rather than a site with no features', () => { diff --git a/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/use-more-features.test.ts b/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/use-more-features.test.ts index 9a99ed72698c..26a4057a7588 100644 --- a/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/use-more-features.test.ts +++ b/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/test/use-more-features.test.ts @@ -89,6 +89,24 @@ describe( 'groupMoreFeatures', () => { expect( monitor.isSwitching ).toBe( true ); } ); + it.each( [ false, true ] )( + 'excludes the helper-owned custom content types module (active: %s)', + activated => { + const groupedWithCpt = groupMoreFeatures( + [], + [ { label: 'Writing', modules: [ 'custom-content-types', 'monitor' ] } ], + { + 'custom-content-types': mod( 'custom-content-types', { activated } ), + monitor: mod( 'monitor' ), + }, + {}, + {} + ); + + expect( slugsOf( groupedWithCpt ) ).toEqual( [ [ 'Writing', [ 'monitor' ] ] ] ); + } + ); + it( 'filters by status and hides modules under plan and essential filters', () => { const filtered = ( filter: Parameters< typeof filterMoreFeatures >[ 1 ] ) => filterMoreFeatures( grouped, filter, '' ).flatMap( group => diff --git a/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/use-more-features.ts b/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/use-more-features.ts index b98400940fb7..9c01308f1e4a 100644 --- a/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/use-more-features.ts +++ b/projects/packages/my-jetpack/_inc/components/my-jetpack-tab-panel/features/use-more-features.ts @@ -77,7 +77,7 @@ function getStateModule( state: FeatureState ): MyJetpackModule | null { * its own card is still that card's, and must not surface here instead. * @param requested - Switch key to the value asked of it. * @param hidden - Modules that do not apply to the site, left out entirely. - * @return Non-empty groups by label, each sorted by name, with every leftover module under Other, last. + * @return Non-empty groups by label, each sorted by name, with eligible ungrouped modules under Other, last. */ export function groupMoreFeatures( features: MainFeature[], @@ -100,6 +100,7 @@ export function groupMoreFeatures( for ( const $module of Object.values( modules ).sort( compareModulesByName ) ) { if ( $module.module === 'vaultpress' || + $module.module === 'custom-content-types' || covered.has( $module.module ) || hidden.has( $module.module ) ) { diff --git a/projects/packages/my-jetpack/_inc/test/app.test.jsx b/projects/packages/my-jetpack/_inc/test/app.test.jsx index 1c8bee1b264e..d6294063e523 100644 --- a/projects/packages/my-jetpack/_inc/test/app.test.jsx +++ b/projects/packages/my-jetpack/_inc/test/app.test.jsx @@ -41,6 +41,16 @@ describe( 'App', () => { expect( screen.getByTestId( 'my-jetpack-screen' ) ).toBeInTheDocument(); } ); + it( 'gives the connection route its scoped scrolling layout', () => { + window.location.hash = '#/connection'; + + render( ); + + const connect = screen.getByRole( 'button', { name: 'Connect your user account' } ); + // eslint-disable-next-line testing-library/no-node-access -- The scrolling layout belongs to the AdminPage root. + expect( connect.closest( '.jp-admin-page' ) ).toHaveClass( 'jp-my-jetpack-connection' ); + } ); + it( 'renders the partner coupon screen in place of the routes', () => { window.location.hash = ''; window.myJetpackInitialState.partnerCoupon = { diff --git a/projects/packages/my-jetpack/changelog/fm-mj-cycle-cpt b/projects/packages/my-jetpack/changelog/fm-mj-cycle-cpt new file mode 100644 index 000000000000..4e3c4295d230 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/fm-mj-cycle-cpt @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Features: Hide the legacy Custom Content Types module. diff --git a/projects/packages/my-jetpack/changelog/fm-mj-cycle-footer b/projects/packages/my-jetpack/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..376e417fb702 --- /dev/null +++ b/projects/packages/my-jetpack/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Connection: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/packages/my-jetpack/changelog/fm-mj-cycle-loading b/projects/packages/my-jetpack/changelog/fm-mj-cycle-loading new file mode 100644 index 000000000000..159bf7b4b95b --- /dev/null +++ b/projects/packages/my-jetpack/changelog/fm-mj-cycle-loading @@ -0,0 +1,3 @@ +Significance: patch +Type: changed +Comment: Avoid an empty state while the unreleased Available filter loads modules. diff --git a/projects/packages/my-jetpack/routes/dashboard/route.scss b/projects/packages/my-jetpack/routes/dashboard/route.scss index 92727adef7f3..d69d280d01b3 100644 --- a/projects/packages/my-jetpack/routes/dashboard/route.scss +++ b/projects/packages/my-jetpack/routes/dashboard/route.scss @@ -8,6 +8,10 @@ body:is(.jetpack_page_my-jetpack, .admin_page_my-jetpack):not(.jetpack-admin-ful @include jetpack-admin-page-layout-wp-build; + .jp-admin-page.jp-my-jetpack-connection { + overflow: auto; + } + // The Jetpack font stack onboarding-screen/styles.module.scss sets on `body`. // Inlined, not imported — that file is a component module, not a partial. font-family: diff --git a/projects/plugins/backup/changelog/fm-mj-cycle-footer b/projects/plugins/backup/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/backup/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/boost/changelog/fm-mj-cycle-footer b/projects/plugins/boost/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/boost/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/jetpack/changelog/fm-mj-cycle-cpt b/projects/plugins/jetpack/changelog/fm-mj-cycle-cpt new file mode 100644 index 000000000000..d51c45b2bc19 --- /dev/null +++ b/projects/plugins/jetpack/changelog/fm-mj-cycle-cpt @@ -0,0 +1,4 @@ +Significance: patch +Type: bugfix + +My Jetpack: Hide the legacy Custom Content Types module from Features. diff --git a/projects/plugins/jetpack/changelog/fm-mj-cycle-footer b/projects/plugins/jetpack/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5debe5b5bb89 --- /dev/null +++ b/projects/plugins/jetpack/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: bugfix + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/protect/changelog/fm-mj-cycle-footer b/projects/plugins/protect/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/protect/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/search/changelog/fm-mj-cycle-footer b/projects/plugins/search/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/search/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/social/changelog/fm-mj-cycle-footer b/projects/plugins/social/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/social/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/stats/changelog/fm-mj-cycle-footer b/projects/plugins/stats/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/stats/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens. diff --git a/projects/plugins/videopress/changelog/fm-mj-cycle-footer b/projects/plugins/videopress/changelog/fm-mj-cycle-footer new file mode 100644 index 000000000000..5f933b5b606e --- /dev/null +++ b/projects/plugins/videopress/changelog/fm-mj-cycle-footer @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +My Jetpack: Make the connection screen's Connect button and footer links reachable on shorter screens.