[Experimental] Product Filters Redesign > Overlay: Add Fullscreen view (#50505)
* Add variation to Product Filters Overlay Navigation * Add changefile(s) from automation for the following project(s): woocommerce-blocks, woocommerce * Move Product Filters Overlay Navigation to correct position * Hide block when it is outside the Product Filters template part * Display Navigation block in the frontend * Show the Product Filters Overlay Navigation on the frontend * Add logic to hide Product Filters Overlay Navigation block on the frontend * Hide block on the Overlay template part * Fix eslint errors * Update the block variation title * Remove the `isActive` property from the block variations * Use Product Filters block context * Replace enum with const * Remove unnecessary `StyleAttributesUtils` * Rename context key * Move BlockOverlayAttribute to the constants.ts file * fix BlockOverlayAttribute import * Fix import error * Improve code for the shouldHideBlock method * Remove unnecessary attributes property * Fix error in ProductFiltersOverlay block * Add dialog to the Product Filters block * Add changefile(s) from automation for the following project(s): woocommerce-blocks, woocommerce * Fix interactivity api error * Prevent block from being hidden on Product Filters template part * Fix inspector controls when block is hidden * Add clickable action to the Product Filters Overlay Navigation block * Fix interactivity directives that were not working for the Overlay * Fix issue with dialog styles not being correctly applied * Add the `closeDialog` functionality * Parse and render blocks for the Product Filters overlay * Fix padding * Fix style for Product Filters Overlay navigation block * Add e2e test * Add e2e test to Product Filters Overlay template part * Fix e2e test * Fix issue causing the trigger button to show even though the overlay mode is set to 'Never" * Fix issue causing close button to not be displayed in the dialog * Add e2e tests * Fix issue that was preventing users from scrolling down the dialog content * Remove text duplication in e2e tests * Remove unnecessary imports * Fix php cs errors * Fix php cs error * Revert changes on Product Gallery modal styles * Fix lint errors * fix php cs lint errors * fix php cs error --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
parent
96497814e4
commit
0b16cfa06a
|
@ -1,3 +1,7 @@
|
||||||
|
body.wc-modal--open {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
body.wc-block-product-gallery-modal-open {
|
body.wc-block-product-gallery-modal-open {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,40 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { store } from '@woocommerce/interactivity';
|
import { getContext as getContextFn, store } from '@woocommerce/interactivity';
|
||||||
|
|
||||||
export interface ProductFiltersContext {
|
export interface ProductFiltersContext {
|
||||||
productId: string;
|
isDialogOpen: boolean;
|
||||||
|
hasPageWithWordPressAdminBar: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getContext = ( ns?: string ) =>
|
||||||
|
getContextFn< ProductFiltersContext >( ns );
|
||||||
|
|
||||||
const productFilters = {
|
const productFilters = {
|
||||||
state: {},
|
state: {
|
||||||
actions: {},
|
isDialogOpen: () => {
|
||||||
|
const context = getContext();
|
||||||
|
return context.isDialogOpen;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
openDialog: () => {
|
||||||
|
const context = getContext();
|
||||||
|
document.body.classList.add( 'wc-modal--open' );
|
||||||
|
context.hasPageWithWordPressAdminBar = Boolean(
|
||||||
|
document.getElementById( 'wpadminbar' )
|
||||||
|
);
|
||||||
|
|
||||||
|
context.isDialogOpen = true;
|
||||||
|
},
|
||||||
|
closeDialog: () => {
|
||||||
|
const context = getContext();
|
||||||
|
document.body.classList.remove( 'wc-modal--open' );
|
||||||
|
|
||||||
|
context.isDialogOpen = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
callbacks: {},
|
callbacks: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { isExperimentalBlocksEnabled } from '@woocommerce/block-settings';
|
||||||
*/
|
*/
|
||||||
import metadata from './block.json';
|
import metadata from './block.json';
|
||||||
import { ProductFiltersBlockSettings } from './settings';
|
import { ProductFiltersBlockSettings } from './settings';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
if ( isExperimentalBlocksEnabled() ) {
|
if ( isExperimentalBlocksEnabled() ) {
|
||||||
registerBlockType( metadata, ProductFiltersBlockSettings );
|
registerBlockType( metadata, ProductFiltersBlockSettings );
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"supports": {
|
"supports": {
|
||||||
|
"interactivity": true,
|
||||||
"align": [ "left", "right", "center"],
|
"align": [ "left", "right", "center"],
|
||||||
"inserter": false,
|
"inserter": false,
|
||||||
"color": {
|
"color": {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { store } from '@woocommerce/interactivity';
|
||||||
|
|
||||||
|
export interface ProductFiltersContext {
|
||||||
|
isDialogOpen: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const productFiltersOverlayNavigation = {
|
||||||
|
state: {},
|
||||||
|
actions: {},
|
||||||
|
callbacks: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
store( 'woocommerce/product-filters', productFiltersOverlayNavigation );
|
||||||
|
|
||||||
|
export type ProductFiltersOverlayNavigation =
|
||||||
|
typeof productFiltersOverlayNavigation;
|
|
@ -1,4 +1,3 @@
|
||||||
/* eslint-disable @wordpress/no-unsafe-wp-apis */
|
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -8,15 +8,18 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&.alignright {
|
&.alignright {
|
||||||
margin-left: auto;
|
justify-content: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.alignleft {
|
&.alignleft {
|
||||||
margin-left: unset;
|
justify-content: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.aligncenter {
|
&.aligncenter {
|
||||||
margin-left: auto;
|
justify-content: center;
|
||||||
margin-right: auto;
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
.wc-block-product-filters {
|
||||||
|
dialog {
|
||||||
|
flex-direction: column;
|
||||||
|
position: fixed;
|
||||||
|
border: none;
|
||||||
|
top: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
|
||||||
|
&.wc-block-product-filters--dialog-open {
|
||||||
|
display: flex;
|
||||||
|
padding-left: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wc-block-product-filters--with-admin-bar {
|
||||||
|
margin-top: $gap;
|
||||||
|
height: calc(100vh - 2 * $gap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,35 @@
|
||||||
*/
|
*/
|
||||||
import { test, expect } from '@woocommerce/e2e-utils';
|
import { test, expect } from '@woocommerce/e2e-utils';
|
||||||
|
|
||||||
|
const templatePartData = {
|
||||||
|
selectors: {
|
||||||
|
frontend: {},
|
||||||
|
editor: {
|
||||||
|
blocks: {
|
||||||
|
activeFilters: {
|
||||||
|
title: 'Active (Experimental)',
|
||||||
|
blockLabel: 'Block: Active (Experimental)',
|
||||||
|
},
|
||||||
|
productFilters: {
|
||||||
|
title: 'Product Filters (Experimental)',
|
||||||
|
blockLabel: 'Block: Product Filters (Experimental)',
|
||||||
|
},
|
||||||
|
filterOptions: {
|
||||||
|
title: 'Filter Options',
|
||||||
|
blockLabel: 'Block: Filter Options',
|
||||||
|
},
|
||||||
|
productFiltersOverlayNavigation: {
|
||||||
|
title: 'Overlay Navigation (Experimental)',
|
||||||
|
name: 'woocommerce/product-filters-overlay-navigation',
|
||||||
|
blockLabel: 'Block: Overlay Navigation (Experimental)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
slug: 'product-filters',
|
||||||
|
productPage: '/product/hoodie/',
|
||||||
|
};
|
||||||
|
|
||||||
test.describe( 'Filters Overlay Template Part', () => {
|
test.describe( 'Filters Overlay Template Part', () => {
|
||||||
test.beforeEach( async ( { admin, requestUtils } ) => {
|
test.beforeEach( async ( { admin, requestUtils } ) => {
|
||||||
await requestUtils.activatePlugin(
|
await requestUtils.activatePlugin(
|
||||||
|
@ -34,10 +63,255 @@ test.describe( 'Filters Overlay Template Part', () => {
|
||||||
.locator( '[data-type="core/template-part"]' )
|
.locator( '[data-type="core/template-part"]' )
|
||||||
.filter( {
|
.filter( {
|
||||||
has: editor.canvas.getByLabel(
|
has: editor.canvas.getByLabel(
|
||||||
'Block: Product Filters (Experimental)'
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.blockLabel
|
||||||
),
|
),
|
||||||
} );
|
} );
|
||||||
|
|
||||||
await expect( productFiltersTemplatePart ).toBeVisible();
|
await expect( productFiltersTemplatePart ).toBeVisible();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
test.describe( 'frontend', () => {
|
||||||
|
test.beforeEach( async ( { admin } ) => {
|
||||||
|
await admin.visitSiteEditor( {
|
||||||
|
postId: `woocommerce/woocommerce//archive-product`,
|
||||||
|
postType: 'wp_template',
|
||||||
|
canvas: 'edit',
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should open and close the dialog when clicking on the Product Filters Overlay Navigation block', async ( {
|
||||||
|
editor,
|
||||||
|
page,
|
||||||
|
frontendUtils,
|
||||||
|
} ) => {
|
||||||
|
await editor.setContent( '' );
|
||||||
|
await editor.openGlobalBlockInserter();
|
||||||
|
await page
|
||||||
|
.getByText(
|
||||||
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.title
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
const block = editor.canvas.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.blockLabel
|
||||||
|
);
|
||||||
|
await expect( block ).toBeVisible();
|
||||||
|
|
||||||
|
// This forces the list view to show the inner blocks of the Product Filters template part.
|
||||||
|
await editor.canvas
|
||||||
|
.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.activeFilters
|
||||||
|
.blockLabel
|
||||||
|
)
|
||||||
|
.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.filterOptions
|
||||||
|
.blockLabel
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await editor.openDocumentSettingsSidebar();
|
||||||
|
await page.getByLabel( 'Document Overview' ).click();
|
||||||
|
await page
|
||||||
|
.getByRole( 'link', {
|
||||||
|
name: templatePartData.selectors.editor.blocks
|
||||||
|
.productFilters.title,
|
||||||
|
} )
|
||||||
|
.nth( 1 )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const layoutSettings = editor.page.getByText(
|
||||||
|
'OverlayNeverMobileAlways'
|
||||||
|
);
|
||||||
|
await layoutSettings.getByLabel( 'Always' ).click();
|
||||||
|
await editor.page
|
||||||
|
.getByRole( 'link', {
|
||||||
|
name: templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.title,
|
||||||
|
} )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await editor.saveSiteEditorEntities( {
|
||||||
|
isOnlyCurrentEntityDirty: false,
|
||||||
|
} );
|
||||||
|
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
|
||||||
|
const productFiltersOverlayNavigation = (
|
||||||
|
await frontendUtils.getBlockByName(
|
||||||
|
templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.name
|
||||||
|
)
|
||||||
|
).filter( {
|
||||||
|
has: page.locator( ':visible' ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
await expect( productFiltersOverlayNavigation ).toBeVisible();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator( '.wc-block-product-filters-overlay-navigation' )
|
||||||
|
.first()
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const productFiltersDialog = page.locator(
|
||||||
|
'.wc-block-product-filters--dialog-open'
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect( productFiltersDialog ).toBeVisible();
|
||||||
|
|
||||||
|
const productFiltersDialogCloseButton = (
|
||||||
|
await frontendUtils.getBlockByName(
|
||||||
|
templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.name
|
||||||
|
)
|
||||||
|
).filter( { hasText: 'Close' } );
|
||||||
|
|
||||||
|
await expect( productFiltersDialogCloseButton ).toBeVisible();
|
||||||
|
|
||||||
|
await productFiltersDialogCloseButton.click();
|
||||||
|
|
||||||
|
await expect( productFiltersDialog ).toBeHidden();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should hide Product Filters Overlay Navigation block when the Overlay mode is set to `Never`', async ( {
|
||||||
|
editor,
|
||||||
|
page,
|
||||||
|
frontendUtils,
|
||||||
|
} ) => {
|
||||||
|
await editor.setContent( '' );
|
||||||
|
await editor.openGlobalBlockInserter();
|
||||||
|
await page
|
||||||
|
.getByText(
|
||||||
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.title
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
const block = editor.canvas.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.blockLabel
|
||||||
|
);
|
||||||
|
await expect( block ).toBeVisible();
|
||||||
|
|
||||||
|
// This forces the list view to show the inner blocks of the Product Filters template part.
|
||||||
|
await editor.canvas
|
||||||
|
.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.activeFilters
|
||||||
|
.blockLabel
|
||||||
|
)
|
||||||
|
.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.filterOptions
|
||||||
|
.blockLabel
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await editor.openDocumentSettingsSidebar();
|
||||||
|
await page.getByLabel( 'Document Overview' ).click();
|
||||||
|
await page
|
||||||
|
.getByRole( 'link', {
|
||||||
|
name: templatePartData.selectors.editor.blocks
|
||||||
|
.productFilters.title,
|
||||||
|
} )
|
||||||
|
.nth( 1 )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const layoutSettings = editor.page.getByText(
|
||||||
|
'OverlayNeverMobileAlways'
|
||||||
|
);
|
||||||
|
await layoutSettings.getByLabel( 'Never' ).click();
|
||||||
|
await editor.page
|
||||||
|
.getByRole( 'link', {
|
||||||
|
name: templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.title,
|
||||||
|
} )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await editor.saveSiteEditorEntities( {
|
||||||
|
isOnlyCurrentEntityDirty: true,
|
||||||
|
} );
|
||||||
|
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
|
||||||
|
const productFiltersOverlayNavigation = (
|
||||||
|
await frontendUtils.getBlockByName(
|
||||||
|
templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.name
|
||||||
|
)
|
||||||
|
).filter( {
|
||||||
|
has: page.locator( ':visible' ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
await expect( productFiltersOverlayNavigation ).toBeHidden();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should hide Product Filters Overlay Navigation block when the Overlay mode is set to `Mobile` and user is on desktop', async ( {
|
||||||
|
editor,
|
||||||
|
page,
|
||||||
|
frontendUtils,
|
||||||
|
} ) => {
|
||||||
|
await editor.setContent( '' );
|
||||||
|
await editor.openGlobalBlockInserter();
|
||||||
|
await page
|
||||||
|
.getByText(
|
||||||
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.title
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
const block = editor.canvas.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.productFilters
|
||||||
|
.blockLabel
|
||||||
|
);
|
||||||
|
await expect( block ).toBeVisible();
|
||||||
|
|
||||||
|
// This forces the list view to show the inner blocks of the Product Filters template part.
|
||||||
|
await editor.canvas
|
||||||
|
.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.activeFilters
|
||||||
|
.blockLabel
|
||||||
|
)
|
||||||
|
.getByLabel(
|
||||||
|
templatePartData.selectors.editor.blocks.filterOptions
|
||||||
|
.blockLabel
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await editor.openDocumentSettingsSidebar();
|
||||||
|
await page.getByLabel( 'Document Overview' ).click();
|
||||||
|
await page
|
||||||
|
.getByRole( 'link', {
|
||||||
|
name: templatePartData.selectors.editor.blocks
|
||||||
|
.productFilters.title,
|
||||||
|
} )
|
||||||
|
.nth( 1 )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const layoutSettings = editor.page.getByText(
|
||||||
|
'OverlayNeverMobileAlways'
|
||||||
|
);
|
||||||
|
await layoutSettings.getByLabel( 'Mobile' ).click();
|
||||||
|
await editor.page
|
||||||
|
.getByRole( 'link', {
|
||||||
|
name: templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.title,
|
||||||
|
} )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await editor.saveSiteEditorEntities( {
|
||||||
|
isOnlyCurrentEntityDirty: false,
|
||||||
|
} );
|
||||||
|
|
||||||
|
await page.goto( '/shop/' );
|
||||||
|
|
||||||
|
const productFiltersOverlayNavigation = (
|
||||||
|
await frontendUtils.getBlockByName(
|
||||||
|
templatePartData.selectors.editor.blocks
|
||||||
|
.productFiltersOverlayNavigation.name
|
||||||
|
)
|
||||||
|
).filter( {
|
||||||
|
has: page.locator( ':visible' ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
await expect( productFiltersOverlayNavigation ).toBeHidden();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -21,6 +21,7 @@ const blockData = {
|
||||||
},
|
},
|
||||||
slug: 'archive-product',
|
slug: 'archive-product',
|
||||||
productPage: '/product/hoodie/',
|
productPage: '/product/hoodie/',
|
||||||
|
shopPage: '/shop/',
|
||||||
};
|
};
|
||||||
|
|
||||||
const test = base.extend< { pageObject: ProductFiltersPage } >( {
|
const test = base.extend< { pageObject: ProductFiltersPage } >( {
|
||||||
|
|
|
@ -43,4 +43,40 @@ export class ProductFiltersPage {
|
||||||
}
|
}
|
||||||
return this.editor.getBlockByName( blockName );
|
return this.editor.getBlockByName( blockName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getProductFiltersOverlayNavigationBlock( {
|
||||||
|
page,
|
||||||
|
}: {
|
||||||
|
page: 'frontend' | 'editor';
|
||||||
|
} ) {
|
||||||
|
const blockName = 'woocommerce/product-filters-overlay-navigation';
|
||||||
|
if ( page === 'frontend' ) {
|
||||||
|
return (
|
||||||
|
await this.frontendUtils.getBlockByName( blockName )
|
||||||
|
).filter( {
|
||||||
|
has: this.page.locator( ':visible' ),
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
return this.editor.canvas.getByLabel(
|
||||||
|
'Block: Overlay Navigation (Experimental)'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectOverlayMode( {
|
||||||
|
mode,
|
||||||
|
}: {
|
||||||
|
mode: 'mobile' | 'always' | 'never';
|
||||||
|
} ) {
|
||||||
|
switch ( mode ) {
|
||||||
|
case 'always':
|
||||||
|
await this.page.getByLabel( 'Always' ).click();
|
||||||
|
break;
|
||||||
|
case 'mobile':
|
||||||
|
await this.page.getByLabel( 'Mobile' ).click();
|
||||||
|
break;
|
||||||
|
case 'never':
|
||||||
|
await this.page.getByLabel( 'Never' ).click();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: patch
|
||||||
|
Type: tweak
|
||||||
|
Comment: Add the Fullscreen view to the Product Filters
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ProductFilters class.
|
* ProductFilters class.
|
||||||
*/
|
*/
|
||||||
|
@ -18,16 +20,91 @@ class ProductFilters extends AbstractBlock {
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
protected function get_block_type_uses_context() {
|
protected function get_block_type_uses_context() {
|
||||||
return [ 'postId' ];
|
return array( 'postId' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the frontend style handle for this block type.
|
* Return the dialog content.
|
||||||
*
|
*
|
||||||
* @return null
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function get_block_type_style() {
|
protected function render_dialog() {
|
||||||
return null;
|
$template_part = BlockTemplateUtils::get_template_part( 'product-filters-overlay' );
|
||||||
|
|
||||||
|
$html = $this->render_template_part( $template_part );
|
||||||
|
|
||||||
|
$html = strtr(
|
||||||
|
'<dialog hidden role="dialog" aria-modal="true">
|
||||||
|
{{html}}
|
||||||
|
</dialog>',
|
||||||
|
array(
|
||||||
|
'{{html}}' => $html,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$p = new \WP_HTML_Tag_Processor( $html );
|
||||||
|
if ( $p->next_tag() ) {
|
||||||
|
$p->set_attribute( 'data-wc-interactive', wp_json_encode( array( 'namespace' => 'woocommerce/product-filters' ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ) );
|
||||||
|
$p->set_attribute( 'data-wc-bind--hidden', '!state.isDialogOpen' );
|
||||||
|
$p->set_attribute( 'data-wc-class--wc-block-product-filters--dialog-open', 'state.isDialogOpen' );
|
||||||
|
$p->set_attribute( 'data-wc-class--wc-block-product-filters--with-admin-bar', 'context.hasPageWithWordPressAdminBar' );
|
||||||
|
$html = $p->get_updated_html();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to render the template part. For each template part, we parse the blocks and render them.
|
||||||
|
*
|
||||||
|
* @param string $template_part The template part to render.
|
||||||
|
* @return string The rendered template part.
|
||||||
|
*/
|
||||||
|
protected function render_template_part( $template_part ) {
|
||||||
|
$parsed_blocks = parse_blocks( $template_part );
|
||||||
|
$wrapper_template_part_block = $parsed_blocks[0];
|
||||||
|
$html = $wrapper_template_part_block['innerHTML'];
|
||||||
|
$target_div = '</div>';
|
||||||
|
|
||||||
|
$template_part_content_html = array_reduce(
|
||||||
|
$wrapper_template_part_block['innerBlocks'],
|
||||||
|
function ( $carry, $item ) {
|
||||||
|
if ( 'core/template-part' === $item['blockName'] ) {
|
||||||
|
$inner_template_part = BlockTemplateUtils::get_template_part( $item['attrs']['slug'] );
|
||||||
|
$inner_template_part_content_html = $this->render_template_part( $inner_template_part );
|
||||||
|
|
||||||
|
return $carry . $inner_template_part_content_html;
|
||||||
|
}
|
||||||
|
return $carry . render_block( $item );
|
||||||
|
},
|
||||||
|
''
|
||||||
|
);
|
||||||
|
|
||||||
|
$html = str_replace( $target_div, $template_part_content_html . $target_div, $html );
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject dialog into the product filters HTML.
|
||||||
|
*
|
||||||
|
* @param string $product_filters_html The Product Filters HTML.
|
||||||
|
* @param string $dialog_html The dialog HTML.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function inject_dialog( $product_filters_html, $dialog_html ) {
|
||||||
|
// Find the position of the last </div>.
|
||||||
|
$pos = strrpos( $product_filters_html, '</div>' );
|
||||||
|
|
||||||
|
if ( $pos ) {
|
||||||
|
// Inject the dialog_html at the correct position.
|
||||||
|
$html = substr_replace( $product_filters_html, $dialog_html, $pos, 0 );
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $product_filters_html;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,6 +116,28 @@ class ProductFilters extends AbstractBlock {
|
||||||
* @return string Rendered block type output.
|
* @return string Rendered block type output.
|
||||||
*/
|
*/
|
||||||
protected function render( $attributes, $content, $block ) {
|
protected function render( $attributes, $content, $block ) {
|
||||||
return $content;
|
$html = $content;
|
||||||
|
$p = new \WP_HTML_Tag_Processor( $html );
|
||||||
|
|
||||||
|
if ( $p->next_tag() ) {
|
||||||
|
$p->set_attribute( 'data-wc-interactive', wp_json_encode( array( 'namespace' => 'woocommerce/product-filters' ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ) );
|
||||||
|
$p->set_attribute(
|
||||||
|
'data-wc-context',
|
||||||
|
wp_json_encode(
|
||||||
|
array(
|
||||||
|
'isDialogOpen' => false,
|
||||||
|
'hasPageWithWordPressAdminBar' => false,
|
||||||
|
),
|
||||||
|
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$html = $p->get_updated_html();
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialog_html = $this->render_dialog();
|
||||||
|
|
||||||
|
$html = $this->inject_dialog( $html, $dialog_html );
|
||||||
|
|
||||||
|
return $html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,17 +21,6 @@ class ProductFiltersOverlayNavigation extends AbstractBlock {
|
||||||
return [ 'woocommerce/product-filters/overlay' ];
|
return [ 'woocommerce/product-filters/overlay' ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the frontend script handle for this block type.
|
|
||||||
*
|
|
||||||
* @see $this->register_block_type()
|
|
||||||
* @param string $key Data to get, or default to everything.
|
|
||||||
* @return array|string|null
|
|
||||||
*/
|
|
||||||
protected function get_block_type_script( $key = null ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Include and render the block.
|
* Include and render the block.
|
||||||
*
|
*
|
||||||
|
@ -46,13 +35,13 @@ class ProductFiltersOverlayNavigation extends AbstractBlock {
|
||||||
'class' => 'wc-block-product-filters-overlay-navigation',
|
'class' => 'wc-block-product-filters-overlay-navigation',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$overlay_mode = $block->context['woocommerce/product-filters/overlay'];
|
$overlay_mode = isset( $block->context['woocommerce/product-filters/overlay'] ) ? $block->context['woocommerce/product-filters/overlay'] : 'never';
|
||||||
|
|
||||||
if ( 'never' === $overlay_mode || ( ! wp_is_mobile() && 'mobile' === $overlay_mode ) ) {
|
if ( 'open-overlay' === $attributes['triggerType'] && ( 'never' === $overlay_mode || ( ! wp_is_mobile() && 'mobile' === $overlay_mode ) ) ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$html_content = strtr(
|
$html = strtr(
|
||||||
'<div {{wrapper_attributes}}>
|
'<div {{wrapper_attributes}}>
|
||||||
{{primary_content}}
|
{{primary_content}}
|
||||||
{{secondary_content}}
|
{{secondary_content}}
|
||||||
|
@ -63,7 +52,20 @@ class ProductFiltersOverlayNavigation extends AbstractBlock {
|
||||||
'{{secondary_content}}' => 'open-overlay' === $attributes['triggerType'] ? $this->render_label( $attributes ) : $this->render_icon( $attributes ),
|
'{{secondary_content}}' => 'open-overlay' === $attributes['triggerType'] ? $this->render_label( $attributes ) : $this->render_icon( $attributes ),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return $html_content;
|
|
||||||
|
$p = new \WP_HTML_Tag_Processor( $html );
|
||||||
|
|
||||||
|
if ( $p->next_tag() ) {
|
||||||
|
$p->set_attribute( 'data-wc-interactive', wp_json_encode( array( 'namespace' => 'woocommerce/product-filters' ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ) );
|
||||||
|
$p->set_attribute(
|
||||||
|
'data-wc-on--click',
|
||||||
|
'open-overlay' === $attributes['triggerType'] ? 'actions.openDialog' : 'actions.closeDialog'
|
||||||
|
);
|
||||||
|
$p->set_attribute( 'data-wc-class--hidden', 'open-overlay' === $attributes['triggerType'] ? 'state.isDialogOpen' : '!state.isDialogOpen' );
|
||||||
|
$html = $p->get_updated_html();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue