| @@ -32,9 +32,9 @@ | ||
| 32 | 32 | <!-- Unified License Activation Bar --> |
| 33 | 33 | <div class="gvlicense-license-bar"> |
| 34 | 34 | <h3><?php esc_html_e( 'Activate License', 'gvectors' ); ?></h3> |
| 35 | 35 | <p class="description" style="margin:0 0 10px;color:#666;font-size:13px;"> |
| 36 | - <?php esc_html_e( 'Enter your license key or transaction ID, or leave empty to automatically find and activate all licenses registered to this domain.', 'gvectors' ); ?> | |
| 36 | + <?php esc_html_e( 'Enter your license key or transaction ID, or leave empty to automatically find and activate all licenses registered to this domain. License keys from our old gVectors store work too.', 'gvectors' ); ?> | |
| 37 | 37 | </p> |
| 38 | 38 | <div class="gvlicense-license-form"> |
| 39 | 39 | <input type="text" id="gvlicense-unified-key" placeholder="<?php esc_attr_e( 'License key, transaction ID, or leave empty for auto-detect...', 'gvectors' ); ?>" class="regular-text"> |
| 40 | 40 | <select id="gvlicense-unified-product" class="gvlicense-product-select"> |
| @@ -63,14 +63,65 @@ | ||
| 63 | 63 | <tbody></tbody> |
| 64 | 64 | </table> |
| 65 | 65 | </div> |
| 66 | 66 | |
| 67 | - <!-- Product Grid (loaded via AJAX) --> | |
| 68 | - <div id="gvlicense-products-grid" class="gvlicense-products-grid"> | |
| 69 | - <div class="gvlicense-loading"> | |
| 70 | - <span class="spinner is-active" style="float:none;"></span> | |
| 71 | - <?php esc_html_e( 'Loading products...', 'gvectors' ); ?> | |
| 67 | + <?php | |
| 68 | + // Product sections (filled via AJAX). Grouping by the Paddle product's parent_slug: | |
| 69 | + // addons = this host's addons, bundles = all bundles, pro = shared products (empty parent_slug) | |
| 70 | + $gvlicense_sections = [ | |
| 71 | + 'addons' => [ | |
| 72 | + 'nav' => __( 'Addons', 'gvectors' ), | |
| 73 | + 'title' => __( 'Addons', 'gvectors' ), | |
| 74 | + 'icon' => '<rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><path d="M17.5 14v7M14 17.5h7"/>', | |
| 75 | + ], | |
| 76 | + 'bundles' => [ | |
| 77 | + 'nav' => __( 'Addon Bundles', 'gvectors' ), | |
| 78 | + 'title' => __( 'Addon Bundles', 'gvectors' ), | |
| 79 | + 'icon' => '<path d="M12 2.5 3 7.5v9l9 5 9-5v-9z"/><path d="m3 7.5 9 5 9-5M12 12.5v9M7.5 5l9 5"/>', | |
| 80 | + ], | |
| 81 | + 'pro' => [ | |
| 82 | + 'nav' => __( 'Pro Plugins', 'gvectors' ), | |
| 83 | + 'title' => __( 'Related PRO Plugins', 'gvectors' ), | |
| 84 | + 'icon' => '<path d="M3 7.5 7.5 12 12 5l4.5 7L21 7.5 19 17H5z"/><path d="M5 20.5h14"/>', | |
| 85 | + ], | |
| 86 | + ]; | |
| 87 | + $gvlicense_svg = function( $paths ) { | |
| 88 | + return '<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">' . $paths . '</svg>'; | |
| 89 | + }; | |
| 90 | + ?> | |
| 91 | + <!-- Products (loaded via AJAX) --> | |
| 92 | + <div id="gvlicense-products" class="gvlicense-products"> | |
| 93 | + <div id="gvlicense-products-status" class="gvlicense-products-status"> | |
| 94 | + <div class="gvlicense-loading"> | |
| 95 | + <span class="spinner is-active" style="float:none;"></span> | |
| 96 | + <?php esc_html_e( 'Loading products...', 'gvectors' ); ?> | |
| 97 | + </div> | |
| 72 | 98 | </div> |
| 99 | + | |
| 100 | + <!-- Section quick navigation (sticky bar above the sections) --> | |
| 101 | + <nav id="gvlicense-section-nav" class="gvlicense-section-nav" aria-label="<?php esc_attr_e( 'Product sections', 'gvectors' ); ?>" hidden> | |
| 102 | + <?php foreach( $gvlicense_sections as $key => $section ): ?> | |
| 103 | + <a href="#gvlicense-section-<?php echo esc_attr( $key ); ?>" class="gvlicense-section-nav-link gvlicense-section-<?php echo esc_attr( $key ); ?>" data-section="<?php echo esc_attr( $key ); ?>"> | |
| 104 | + <span class="gvlicense-section-icon"><?php echo $gvlicense_svg( $section['icon'] ); // phpcs:ignore WordPress.Security.EscapeOutput -- static markup ?></span> | |
| 105 | + <span class="gvlicense-section-nav-label"><?php echo esc_html( $section['nav'] ); ?></span> | |
| 106 | + <span class="gvlicense-section-count"></span> | |
| 107 | + </a> | |
| 108 | + <?php endforeach; ?> | |
| 109 | + <button type="button" class="gvlicense-section-nav-top" title="<?php esc_attr_e( 'Back to top', 'gvectors' ); ?>" aria-label="<?php esc_attr_e( 'Back to top', 'gvectors' ); ?>"> | |
| 110 | + <?php echo $gvlicense_svg( '<path d="M12 19V5M5.5 11.5 12 5l6.5 6.5"/>' ); // phpcs:ignore WordPress.Security.EscapeOutput -- static markup ?> | |
| 111 | + </button> | |
| 112 | + </nav> | |
| 113 | + | |
| 114 | + <?php foreach( $gvlicense_sections as $key => $section ): ?> | |
| 115 | + <section id="gvlicense-section-<?php echo esc_attr( $key ); ?>" class="gvlicense-products-section gvlicense-section-<?php echo esc_attr( $key ); ?>" data-section="<?php echo esc_attr( $key ); ?>" tabindex="-1" hidden> | |
| 116 | + <h2 class="gvlicense-section-title"> | |
| 117 | + <span class="gvlicense-section-icon"><?php echo $gvlicense_svg( $section['icon'] ); // phpcs:ignore WordPress.Security.EscapeOutput -- static markup ?></span> | |
| 118 | + <?php echo esc_html( $section['title'] ); ?> | |
| 119 | + <span class="gvlicense-section-count"></span> | |
| 120 | + </h2> | |
| 121 | + <div class="gvlicense-products-grid"></div> | |
| 122 | + </section> | |
| 123 | + <?php endforeach; ?> | |
| 73 | 124 | </div> |
| 74 | 125 | |
| 75 | 126 | <div style="clear:both;"></div> |
| 76 | 127 | </div> |
| @@ -123,8 +174,18 @@ | ||
| 123 | 174 | <# } #> |
| 124 | 175 | </ul> |
| 125 | 176 | </div> |
| 126 | 177 | <# } #> |
| 178 | + <# if (data.product_url || data.demo_url) { #> | |
| 179 | + <div class="gvlicense-product-links"> | |
| 180 | + <# if (data.product_url) { #> | |
| 181 | + <a class="button button-small gvlicense-product-link" href="{{data.product_url}}" target="_blank" rel="noopener noreferrer"><span class="dashicons dashicons-external"></span> <?php esc_html_e( 'View Features', 'gvectors' ); ?><span class="screen-reader-text"> <?php esc_html_e( '(opens in a new tab)', 'gvectors' ); ?></span></a> | |
| 182 | + <# } #> | |
| 183 | + <# if (data.demo_url) { #> | |
| 184 | + <a class="button button-small gvlicense-demo-link" href="{{data.demo_url}}" target="_blank" rel="noopener noreferrer"><span class="dashicons dashicons-visibility"></span> <?php esc_html_e( 'Live Demo', 'gvectors' ); ?><span class="screen-reader-text"> <?php esc_html_e( '(opens in a new tab)', 'gvectors' ); ?></span></a> | |
| 185 | + <# } #> | |
| 186 | + </div> | |
| 187 | + <# } #> | |
| 127 | 188 | <div class="gvlicense-product-price"> |
| 128 | 189 | <# if (data.is_licensed || data.is_trial) { #> |
| 129 | 190 | <# if (data.active_plan_name) { #> |
| 130 | 191 | <span class="gvlicense-active-plan">{{data.active_plan_name}}</span> |
| @@ -175,12 +236,26 @@ | ||
| 175 | 236 | <# if (data.addon_status === 'active') { #> |
| 176 | 237 | <span class="gvlicense-addon-active"><span class="dashicons dashicons-yes-alt"></span> <?php esc_html_e( 'Active', 'gvectors' ); ?></span> |
| 177 | 238 | <# } else if (data.addon_status === 'installed') { #> |
| 178 | 239 | <button type="button" class="button button-primary gvlicense-activate-addon-btn" data-product-id="{{data.id}}" data-plugin-slug="{{data.plugin_slug}}"><?php esc_html_e( 'Activate', 'gvectors' ); ?></button> |
| 240 | + <# } else if (data.can_install === false) { #> | |
| 241 | + <button type="button" class="button button-primary gvlicense-download-btn" data-product-id="{{data.id}}"><span class="dashicons dashicons-download"></span> <?php esc_html_e( 'Download ZIP', 'gvectors' ); ?></button> | |
| 179 | 242 | <# } else { #> |
| 180 | 243 | <button type="button" class="button button-primary gvlicense-install-btn" data-product-id="{{data.id}}"><?php esc_html_e( 'Install & Activate', 'gvectors' ); ?></button> |
| 244 | + <# if (data.offer_download) { #> | |
| 245 | + <button type="button" class="button gvlicense-download-btn gvlicense-download-icon-btn" data-product-id="{{data.id}}" title="<?php esc_attr_e( 'Download ZIP for manual installation', 'gvectors' ); ?>" aria-label="<?php esc_attr_e( 'Download ZIP for manual installation', 'gvectors' ); ?>"><span class="dashicons dashicons-download"></span></button> | |
| 181 | 246 | <# } #> |
| 247 | + <# } #> | |
| 248 | + <# if (data.offer_verified_copy) { #> | |
| 249 | + <button type="button" class="button<# if (data.needs_verified_copy) { #> button-primary<# } #> gvlicense-verified-copy-btn" data-product-id="{{data.id}}"><span class="dashicons dashicons-update"></span> <?php esc_html_e( 'Reinstall Addon', 'gvectors' ); ?></button> | |
| 250 | + <# } #> | |
| 182 | 251 | <button type="button" class="button gvlicense-manage-btn" data-product-id="{{data.id}}"><?php esc_html_e( 'Manage', 'gvectors' ); ?></button> |
| 252 | + <# if (data.offer_download) { #> | |
| 253 | + <p class="gvlicense-manual-hint"><?php esc_html_e( 'WordPress can\'t install addons automatically on this site — download the ZIP and install it manually.', 'gvectors' ); ?></p> | |
| 254 | + <# } #> | |
| 255 | + <# if (data.needs_verified_copy) { #> | |
| 256 | + <p class="gvlicense-manual-hint"><?php esc_html_e( 'This copy isn\'t verified for this site (installed outside the Addons page, or its files were changed). Reinstall it from the store — your settings and data are kept.', 'gvectors' ); ?></p> | |
| 257 | + <# } #> | |
| 183 | 258 | <# } else { #> |
| 184 | 259 | <# if (data.prices && data.prices.length) { #> |
| 185 | 260 | <button type="button" class="button button-primary gvlicense-buy-btn" data-price-id="{{_defaultPriceId}}" data-product-id="{{data.id}}"><?php esc_html_e( 'Buy Now', 'gvectors' ); ?></button> |
| 186 | 261 | <# } #> |