feat: add preview modal#593
Conversation
|
Tip You can preview the changes in the Playground Plugin build for e766a3d is ready 🛎️!
|
There was a problem hiding this comment.
Pull request overview
Adds a “Save & Preview” flow to the PPOM field-group editor, allowing admins to open a live product-page preview for the current group.
Changes:
- Adds a disabled-by-default “Save & Preview” button and a live preview modal to the PPOM fields admin screen.
- Implements modal behavior in a new admin JS controller, integrating Select2 product search and iframe-based preview refresh.
- Introduces new admin-ajax handlers to resolve preview URLs and search products, plus related localized data and CSS styling.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/admin/ppom-fields.php | Adds the “Save & Preview” button and the live preview modal markup on the edit screen. |
| js/admin/ppom-preview-modal.js | New controller for preview modal open/refresh, availability checks, and Select2 product search. |
| js/admin/ppom-admin.js | Hooks into the existing save flow to optionally open preview after successful save; emits attachment-update event. |
| css/ppom-admin.css | Adds styling for the preview modal layout, notices, and iframe container. |
| classes/fields.class.php | Enqueues the new script and localizes preview data; adds helper to collect directly assigned products. |
| classes/admin.class.php | Adds AJAX endpoints for preview URL resolution and product search, plus supporting product-resolution helpers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $query = new WP_Query( | ||
| array( | ||
| 'post_type' => 'product', | ||
| 'post_status' => 'publish', | ||
| 'posts_per_page' => -1, | ||
| 'fields' => 'ids', | ||
| 'tax_query' => $tax_query, | ||
| 'orderby' => 'modified', | ||
| 'order' => 'DESC', | ||
| 'no_found_rows' => true, | ||
| ) | ||
| ); |
There was a problem hiding this comment.
get_category_tag_product_ids_for_ppom() fetches all matching products (posts_per_page => -1) even though resolve_preview_product_id() only uses the first result. To reduce load on large catalogs, set posts_per_page to 1 (and keep orderby => modified, fields => ids, no_found_rows => true) so the database does the limiting.
| add_action( 'wp_ajax_ppom_attach_ppoms', array( $this, 'ppom_attach_ppoms' ) ); | ||
| add_action( 'wp_ajax_ppom_get_preview_url', array( $this, 'get_preview_url' ) ); | ||
| add_action( 'wp_ajax_ppom_search_products', array( $this, 'search_products' ) ); |
There was a problem hiding this comment.
New AJAX endpoints (ppom_get_preview_url, ppom_search_products) introduce important behavior (permission/nonce enforcement, product resolution, and empty-state codes) but there are no corresponding unit tests. Since this repo already has WP unit tests for admin behavior (e.g., tests/unit/test-rest-and-admin.php), please add coverage for: (1) unauthorized/invalid nonce returns error, (2) ppom_preview_no_product when no eligible products exist, and (3) success payload shape for both handlers.
| <?php if ( $is_edit_screen && ! $is_new_group ) { ?> | ||
| <span class="ppom-save-preview-tooltip-anchor" title=""> | ||
| <button type="button" class="btn btn-secondary ppom-save-and-preview" disabled="disabled" aria-disabled="true"> | ||
| <?php _e( 'Save & Preview', 'woocommerce-product-addon' ); ?> | ||
| </button> | ||
| </span> |
There was a problem hiding this comment.
PR description indicates "Will affect visual aspect of the product: NO", but this template adds a new "Save & Preview" button and a live preview modal. Please update the PR metadata to reflect that this introduces UI/visual changes (or remove the UI changes if that section is intended to remain "NO").
| protected function get_assigned_products_for_meta( $ppom_id ) { | ||
| $query = new WP_Query( | ||
| array( | ||
| 'post_type' => 'product', | ||
| 'post_status' => 'publish', | ||
| 'posts_per_page' => -1, | ||
| 'fields' => 'ids', | ||
| 'no_found_rows' => true, | ||
| ) | ||
| ); |
There was a problem hiding this comment.
get_assigned_products_for_meta() loads all published products (posts_per_page => -1) and then calls get_post_meta() per product to find assignments. On large catalogs this will be very slow on every field-group edit screen load. Consider replacing this with a query that directly filters by PPOM_PRODUCT_META_KEY (e.g., meta_query with = for legacy single values plus LIKE for serialized arrays using a safe token such as i:<ppom_id>;), and let the query sort by modified so the manual usort()/get_post() loop can be removed.
| 'previewLoading' => __( 'Loading preview...', 'woocommerce-product-addon' ), | ||
| 'previewNoProduct' => __( 'No eligible product found for preview. Assign this group to products/categories/tags and try again.', 'woocommerce-product-addon' ), | ||
| 'previewNoUrl' => __( 'Could not load the preview URL.', 'woocommerce-product-addon' ), | ||
| 'previewSaveFirst' => __( 'Save failed. Fix errors before opening preview.', 'woocommerce-product-addon' ), | ||
| 'previewSelectPlaceholder' => __( 'Search products...', 'woocommerce-product-addon' ), | ||
| 'previewGoToAssignment' => __( 'Go to assignment', 'woocommerce-product-addon' ), | ||
| 'previewCheckingAvailability' => __( 'Checking preview availability...', 'woocommerce-product-addon' ), | ||
| 'previewDisabledHint' => __( 'Attach this group to at least one product, category, or tag to enable preview.', 'woocommerce-product-addon' ), |
There was a problem hiding this comment.
The newly added i18n keys previewNoProduct and previewSaveFirst are not referenced by js/admin/ppom-preview-modal.js (the modal uses previewDisabledHint / previewNoUrl instead). Keeping unused strings increases translation surface area; either use these keys in the JS flow or remove them.
| protected function get_direct_product_ids_for_ppom( $ppom_id ) { | ||
| $query = new WP_Query( | ||
| array( | ||
| 'post_type' => 'product', | ||
| 'post_status' => 'publish', | ||
| 'posts_per_page' => -1, | ||
| 'fields' => 'ids', | ||
| 'no_found_rows' => true, | ||
| ) | ||
| ); | ||
|
|
||
| if ( empty( $query->posts ) ) { | ||
| return array(); | ||
| } | ||
|
|
||
| $attached_product_ids = array(); | ||
| foreach ( $query->posts as $product_id ) { | ||
| if ( ! is_int( $product_id ) ) { | ||
| continue; | ||
| } | ||
|
|
||
| $attached_meta = get_post_meta( $product_id, PPOM_PRODUCT_META_KEY, true ); | ||
|
|
||
| if ( is_array( $attached_meta ) && in_array( $ppom_id, array_map( 'intval', $attached_meta ), true ) ) { | ||
| $attached_product_ids[] = (int) $product_id; | ||
| continue; | ||
| } | ||
|
|
||
| if ( is_numeric( $attached_meta ) && (int) $attached_meta === $ppom_id ) { | ||
| $attached_product_ids[] = (int) $product_id; | ||
| } | ||
| } |
There was a problem hiding this comment.
get_direct_product_ids_for_ppom() currently queries all products and then performs per-product get_post_meta() checks to find assignments. This is O(n) over the entire catalog and will not scale. Prefer a WP_Query (or direct SQL) that filters by meta_key => PPOM_PRODUCT_META_KEY and matches either the legacy scalar value (=) or the serialized-array representation (LIKE on a safe pattern such as i:<ppom_id>;), with orderby => modified so you can drop the additional recency sort step.
|
@Soare-Robert-Daniel, The modal preview looks good, it would be great if we could improve the alignment of the dropdown and refresh button like this. |

Summary
Will affect visual aspect of the product
NO
Screenshots
Test instructions
Check before Pull Request is ready:
Closes https://github.com/Codeinwp/ppom-pro/issues/649