From 1a217fa77419b8fd2483a0f615d1b148b9341cc7 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 2 Oct 2023 16:31:03 +0200 Subject: [PATCH 1/9] Product Gallery Thumbnails: Add View All link to the last thumbnail (non-interactive) --- assets/js/blocks/product-gallery/style.scss | 30 +++++++++++- src/BlockTypes/ProductGalleryThumbnails.php | 53 ++++++++++++++++++--- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/assets/js/blocks/product-gallery/style.scss b/assets/js/blocks/product-gallery/style.scss index 314ba66f912..80e8695b1d4 100644 --- a/assets/js/blocks/product-gallery/style.scss +++ b/assets/js/blocks/product-gallery/style.scss @@ -212,7 +212,35 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset)); width: 100px; height: 100px; margin: 5px; + position: relative; } -} + .wc-block-product-gallery-thumbnails__thumbnail__overlay { + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: absolute; + background-color: rgba(0, 0, 0, 0.3); + top: 0; + left: 0; + width: 100%; + height: 100%; + + .wc-block-product-gallery-thumbnails__thumbnail__remaining-thumbnails-count { + @include font-size(large); + font-weight: 700; + } + + .wc-block-product-gallery-thumbnails__thumbnail__view-all { + text-decoration: underline; + } + + .wc-block-product-gallery-thumbnails__thumbnail__remaining-thumbnails-count, + .wc-block-product-gallery-thumbnails__thumbnail__view-all { + color: #fff; + } + } +} diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index be083c13290..159f964e968 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -40,6 +40,38 @@ protected function get_block_type_uses_context() { return [ 'productGalleryClientId', 'postId', 'thumbnailsNumberOfThumbnails', 'thumbnailsPosition' ]; } + /** + * Generate the View All markup. + * + * @param int $remaining_thumbnails_count The number of thumbnails that are not displayed. + * + * @return string + */ + protected function generate_view_all_html( $remaining_thumbnails_count ) { + return ''; + } + + /** + * Inject View All markup into the product thumbnail HTML. + * + * @param string $thumbnail_html The thumbnail HTML. + * @param string $view_all_html The view all HTML. + * + * @return string + */ + protected function inject_view_all( $thumbnail_html, $view_all_html ) { + + // Find the position of the last . + $pos = strrpos( $thumbnail_html, '' ); + + if ( false !== $pos ) { + // Inject the view_all_html at the correct position. + $html = substr_replace( $thumbnail_html, $view_all_html, $pos, 0 ); + + return $html; + } + } + /** * Include and render the block. * @@ -74,15 +106,22 @@ protected function render( $attributes, $content, $block ) { break; } - $processor = new \WP_HTML_Tag_Processor( $product_gallery_image_html ); + // If it's the last thumbnail and the number of product gallery images is greater than the number of thumbnails settings output the View All markup. + if ( $thumbnails_count === $number_of_thumbnails && count( $product_gallery_images ) > $number_of_thumbnails ) { + $remaining_thumbnails_count = count( $product_gallery_images ) - $number_of_thumbnails; + $product_gallery_image_html = $this->inject_view_all( $product_gallery_image_html, $this->generate_view_all_html( $remaining_thumbnails_count ) ); + $html .= $product_gallery_image_html; + } else { + $processor = new \WP_HTML_Tag_Processor( $product_gallery_image_html ); - if ( $processor->next_tag( 'img' ) ) { - $processor->set_attribute( - 'data-wc-on--click', - 'actions.woocommerce.thumbnails.handleClick' - ); + if ( $processor->next_tag( 'img' ) ) { + $processor->set_attribute( + 'data-wc-on--click', + 'actions.woocommerce.thumbnails.handleClick' + ); - $html .= $processor->get_updated_html(); + $html .= $processor->get_updated_html(); + } } $thumbnails_count++; From 59fe8df29059d7d637ba3e58b5eba1fd36a970b8 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 2 Oct 2023 20:27:07 +0200 Subject: [PATCH 2/9] Product Gallery Thumbnails: Add interactivity to the View All overlay --- .../inner-blocks/product-gallery-large-image/frontend.tsx | 6 +++++- assets/js/blocks/product-gallery/style.scss | 4 ++-- src/BlockTypes/ProductGalleryLargeImage.php | 2 +- src/BlockTypes/ProductGalleryThumbnails.php | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/assets/js/blocks/product-gallery/inner-blocks/product-gallery-large-image/frontend.tsx b/assets/js/blocks/product-gallery/inner-blocks/product-gallery-large-image/frontend.tsx index b5d193b8207..74a54c27fdc 100644 --- a/assets/js/blocks/product-gallery/inner-blocks/product-gallery-large-image/frontend.tsx +++ b/assets/js/blocks/product-gallery/inner-blocks/product-gallery-large-image/frontend.tsx @@ -72,7 +72,11 @@ interactivityStore( context: Context; event: Event; } ) => { - if ( ( event.target as HTMLElement ).tagName === 'IMG' ) { + if ( + ( event.target as HTMLElement ).classList.contains( + 'wc-block-product-gallery-dialog-on-click' + ) + ) { context.woocommerce.isDialogOpen = true; } }, diff --git a/assets/js/blocks/product-gallery/style.scss b/assets/js/blocks/product-gallery/style.scss index 80e8695b1d4..87840469b95 100644 --- a/assets/js/blocks/product-gallery/style.scss +++ b/assets/js/blocks/product-gallery/style.scss @@ -223,9 +223,8 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset)); align-items: center; justify-content: center; position: absolute; - background-color: rgba(0, 0, 0, 0.3); + background-color: rgba(0, 0, 0, 0.4); top: 0; - left: 0; width: 100%; height: 100%; @@ -235,6 +234,7 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset)); } .wc-block-product-gallery-thumbnails__thumbnail__view-all { + @include font-size(smaller); text-decoration: underline; } diff --git a/src/BlockTypes/ProductGalleryLargeImage.php b/src/BlockTypes/ProductGalleryLargeImage.php index 31062e91c90..5e25a8aaaf9 100644 --- a/src/BlockTypes/ProductGalleryLargeImage.php +++ b/src/BlockTypes/ProductGalleryLargeImage.php @@ -125,7 +125,7 @@ private function get_main_images_html( $context, $product_id ) { ); if ( $context['fullScreenOnClick'] ) { - $attributes['class'] .= ' wc-block-woocommerce-product-gallery-large-image__image--full-screen-on-click'; + $attributes['class'] .= ' wc-block-woocommerce-product-gallery-large-image__image--full-screen-on-click wc-block-product-gallery-dialog-on-click'; } if ( $context['hoverZoom'] ) { diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index 159f964e968..72e8fd8874e 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -48,7 +48,7 @@ protected function get_block_type_uses_context() { * @return string */ protected function generate_view_all_html( $remaining_thumbnails_count ) { - return ''; + return ''; } /** From 0dac111c6a6299b0b18f2671df4bbf7ef38e23c3 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 9 Oct 2023 15:19:20 +0200 Subject: [PATCH 3/9] Product Gallery Thumbnails: Refactor View all html to make it more readable --- src/BlockTypes/ProductGalleryThumbnails.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index 72e8fd8874e..e2cf8bb975c 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -48,7 +48,16 @@ protected function get_block_type_uses_context() { * @return string */ protected function generate_view_all_html( $remaining_thumbnails_count ) { - return ''; + $view_all_html = ''; + + return sprintf( + $view_all_html, + esc_html( $remaining_thumbnails_count ), + __( 'View all', 'woo-gutenberg-products-block' ) + ); } /** From 624035d36ffa01a0182c40024c605bc28d2423c8 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 9 Oct 2023 16:21:07 +0200 Subject: [PATCH 4/9] Product Gallery Thumbnails: Fix #11100 - Load all thumbnails and hide the View all overlay when in Dialog --- assets/js/blocks/product-gallery/block.json | 3 ++- .../inner-blocks/product-gallery-thumbnails/block.json | 2 +- src/BlockTypes/ProductGalleryThumbnails.php | 10 ++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/assets/js/blocks/product-gallery/block.json b/assets/js/blocks/product-gallery/block.json index 7a6219d5ec3..70ef7da1f17 100644 --- a/assets/js/blocks/product-gallery/block.json +++ b/assets/js/blocks/product-gallery/block.json @@ -21,7 +21,8 @@ "nextPreviousButtonsPosition": "nextPreviousButtonsPosition", "pagerDisplayMode": "pagerDisplayMode", "hoverZoom": "hoverZoom", - "fullScreenOnClick": "fullScreenOnClick" + "fullScreenOnClick": "fullScreenOnClick", + "mode": "mode" }, "usesContext": [ "postId" ], "attributes": { diff --git a/assets/js/blocks/product-gallery/inner-blocks/product-gallery-thumbnails/block.json b/assets/js/blocks/product-gallery/inner-blocks/product-gallery-thumbnails/block.json index 17e54305445..4cb598b27f2 100644 --- a/assets/js/blocks/product-gallery/inner-blocks/product-gallery-thumbnails/block.json +++ b/assets/js/blocks/product-gallery/inner-blocks/product-gallery-thumbnails/block.json @@ -7,7 +7,7 @@ "description": "Display the Thumbnails of a product.", "category": "woocommerce", "keywords": [ "WooCommerce" ], - "usesContext": [ "postId", "thumbnailsPosition", "thumbnailsNumberOfThumbnails", "productGalleryClientId" ], + "usesContext": [ "postId", "thumbnailsPosition", "thumbnailsNumberOfThumbnails", "productGalleryClientId", "mode" ], "textdomain": "woo-gutenberg-products-block", "ancestor": [ "woocommerce/product-gallery" ], "supports": { diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index e2cf8bb975c..0ce0791ac45 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -37,7 +37,7 @@ protected function get_block_type_style() { * @return string[] */ protected function get_block_type_uses_context() { - return [ 'productGalleryClientId', 'postId', 'thumbnailsNumberOfThumbnails', 'thumbnailsPosition' ]; + return [ 'productGalleryClientId', 'postId', 'thumbnailsNumberOfThumbnails', 'thumbnailsPosition', 'mode' ]; } /** @@ -108,15 +108,17 @@ protected function render( $attributes, $content, $block ) { if ( $product_gallery_images && $post_thumbnail_id ) { $html = ''; $number_of_thumbnails = isset( $block->context['thumbnailsNumberOfThumbnails'] ) ? $block->context['thumbnailsNumberOfThumbnails'] : 3; + $mode = $block->context['mode'] ?? ''; $thumbnails_count = 1; foreach ( $product_gallery_images as $product_gallery_image_html ) { - if ( $thumbnails_count > $number_of_thumbnails ) { + // Limit the number of thumbnails only in the standard mode (and not in dialog). + if ( 'standard' === $mode && $thumbnails_count > $number_of_thumbnails ) { break; } - // If it's the last thumbnail and the number of product gallery images is greater than the number of thumbnails settings output the View All markup. - if ( $thumbnails_count === $number_of_thumbnails && count( $product_gallery_images ) > $number_of_thumbnails ) { + // If not in dialog and it's the last thumbnail and the number of product gallery images is greater than the number of thumbnails settings output the View All markup. + if ( 'standard' === $mode && $thumbnails_count === $number_of_thumbnails && count( $product_gallery_images ) > $number_of_thumbnails ) { $remaining_thumbnails_count = count( $product_gallery_images ) - $number_of_thumbnails; $product_gallery_image_html = $this->inject_view_all( $product_gallery_image_html, $this->generate_view_all_html( $remaining_thumbnails_count ) ); $html .= $product_gallery_image_html; From bb719e8c6af7c7fb9b5be2bf25a096298bc3cb79 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 9 Oct 2023 22:05:50 +0200 Subject: [PATCH 5/9] Product Gallery Thumbnails: Fix #11099 - Enable the dialog for the View all thumbnails overlay even when the 'Full-screen when clicked' setting is disabled --- src/BlockTypes/ProductGallery.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BlockTypes/ProductGallery.php b/src/BlockTypes/ProductGallery.php index 8a491c727a9..047e71550e0 100644 --- a/src/BlockTypes/ProductGallery.php +++ b/src/BlockTypes/ProductGallery.php @@ -123,7 +123,7 @@ protected function render( $attributes, $content, $block ) { $number_of_thumbnails = $block->attributes['thumbnailsNumberOfThumbnails'] ?? 0; $classname = $attributes['className'] ?? ''; - $dialog = ( true === $attributes['fullScreenOnClick'] && isset( $attributes['mode'] ) && 'full' !== $attributes['mode'] ) ? $this->render_dialog() : ''; + $dialog = isset( $attributes['mode'] ) && 'full' !== $attributes['mode'] ? $this->render_dialog() : ''; $post_id = $block->context['postId'] ?? ''; $product = wc_get_product( $post_id ); From 1dc1f58a2ca53fe2f62ac3b7592c7b886aae5570 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Wed, 11 Oct 2023 14:40:41 +0200 Subject: [PATCH 6/9] Product Gallery Thumbnails: Remove unnecessary concatenation from the View all html --- src/BlockTypes/ProductGalleryThumbnails.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index 0ce0791ac45..bc195e93ed3 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -48,10 +48,10 @@ protected function get_block_type_uses_context() { * @return string */ protected function generate_view_all_html( $remaining_thumbnails_count ) { - $view_all_html = ''; + $view_all_html = ''; return sprintf( $view_all_html, From b3f5ea3c0c06760572359d9b8054e73f9bfa5afb Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Tue, 17 Oct 2023 13:32:04 +0200 Subject: [PATCH 7/9] Product Gallery Thumbnails: Abstract the View All conditions into separate functions for readability --- src/BlockTypes/ProductGalleryThumbnails.php | 33 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index bc195e93ed3..80e10111069 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -81,6 +81,35 @@ protected function inject_view_all( $thumbnail_html, $view_all_html ) { } } + /** + * Check if the thumbnails should be limited. + * + * @param string $mode Mode of the gallery. Expected values: 'standard'. + * @param int $thumbnails_count Current count of processed thumbnails. + * @param int $number_of_thumbnails Number of thumbnails configured to display. + * + * @return bool + */ + protected function should_limit_thumbnails( $mode, $thumbnails_count, $number_of_thumbnails ) { + return 'standard' === $mode && $thumbnails_count > $number_of_thumbnails; + } + + /** + * Check if View All markup should be displayed. + * + * @param string $mode Mode of the gallery. Expected values: 'standard'. + * @param int $thumbnails_count Current count of processed thumbnails. + * @param array $product_gallery_images Array of product gallery image HTML strings. + * @param int $number_of_thumbnails Number of thumbnails configured to display. + * + * @return bool + */ + protected function should_display_view_all( $mode, $thumbnails_count, $product_gallery_images, $number_of_thumbnails ) { + return 'standard' === $mode && + $thumbnails_count === $number_of_thumbnails && + count( $product_gallery_images ) > $number_of_thumbnails; + } + /** * Include and render the block. * @@ -113,12 +142,12 @@ protected function render( $attributes, $content, $block ) { foreach ( $product_gallery_images as $product_gallery_image_html ) { // Limit the number of thumbnails only in the standard mode (and not in dialog). - if ( 'standard' === $mode && $thumbnails_count > $number_of_thumbnails ) { + if ( $this->should_limit_thumbnails( $mode, $thumbnails_count, $number_of_thumbnails ) ) { break; } // If not in dialog and it's the last thumbnail and the number of product gallery images is greater than the number of thumbnails settings output the View All markup. - if ( 'standard' === $mode && $thumbnails_count === $number_of_thumbnails && count( $product_gallery_images ) > $number_of_thumbnails ) { + if ( $this->should_display_view_all( $mode, $thumbnails_count, $product_gallery_images, $number_of_thumbnails ) ) { $remaining_thumbnails_count = count( $product_gallery_images ) - $number_of_thumbnails; $product_gallery_image_html = $this->inject_view_all( $product_gallery_image_html, $this->generate_view_all_html( $remaining_thumbnails_count ) ); $html .= $product_gallery_image_html; From cec7e0309be1416c8c01b34b0fd13b5aaa90e4b6 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Wed, 18 Oct 2023 12:50:23 +0200 Subject: [PATCH 8/9] Product Gallery Thumbnails: Add escaping to the View all plain text string --- src/BlockTypes/ProductGalleryThumbnails.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BlockTypes/ProductGalleryThumbnails.php b/src/BlockTypes/ProductGalleryThumbnails.php index 80e10111069..2e82ad1fe35 100644 --- a/src/BlockTypes/ProductGalleryThumbnails.php +++ b/src/BlockTypes/ProductGalleryThumbnails.php @@ -56,7 +56,7 @@ protected function generate_view_all_html( $remaining_thumbnails_count ) { return sprintf( $view_all_html, esc_html( $remaining_thumbnails_count ), - __( 'View all', 'woo-gutenberg-products-block' ) + esc_html__( 'View all', 'woo-gutenberg-products-block' ) ); } From eacfa93db720f440a85998ea1038782077611968 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Tue, 31 Oct 2023 21:35:25 +0100 Subject: [PATCH 9/9] E2E: Fix the Sale Badge and Single Product Template tests by selecting the first Sale Badge --- ...e-single-product-template.block_theme.side_effects.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.side_effects.spec.ts b/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.side_effects.spec.ts index e2fb4906f02..aacd2256f2e 100644 --- a/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.side_effects.spec.ts +++ b/tests/e2e/tests/on-sale-badge/on-sale-badge-single-product-template.block_theme.side_effects.spec.ts @@ -59,12 +59,14 @@ const getBoundingClientRect = async ( { blockData.selectors[ isFrontend ? 'frontend' : 'editor' ] .productSaleBadge ) + .first() .evaluate( ( el ) => el.getBoundingClientRect() ), productSaleBadgeContainer: await page .locator( blockData.selectors[ isFrontend ? 'frontend' : 'editor' ] .productSaleBadgeContainer ) + .first() .evaluate( ( el ) => el.getBoundingClientRect() ), }; }; @@ -127,7 +129,7 @@ test.describe( `${ blockData.name }`, () => { const block = await frontendUtils.getBlockByName( blockData.name ); - await expect( block ).toBeVisible(); + await expect( block.first() ).toBeVisible(); } ); test( `should be not rendered when the product isn't on sale the frontend side`, async ( {