diff --git a/classes/Visualizer/Module/Admin.php b/classes/Visualizer/Module/Admin.php
index 7e3a508a..614f829f 100644
--- a/classes/Visualizer/Module/Admin.php
+++ b/classes/Visualizer/Module/Admin.php
@@ -1022,6 +1022,7 @@ public function renderLibraryPage() {
}
// enqueue charts array
$ajaxurl = admin_url( 'admin-ajax.php' );
+
wp_localize_script(
'visualizer-library',
'visualizer',
diff --git a/classes/Visualizer/Plugin.php b/classes/Visualizer/Plugin.php
index 49517b51..3f20628a 100644
--- a/classes/Visualizer/Plugin.php
+++ b/classes/Visualizer/Plugin.php
@@ -57,6 +57,8 @@ class Visualizer_Plugin {
const ACTION_UPLOAD_DATA = 'visualizer-upload-data';
const ACTION_EXPORT_DATA = 'visualizer-export-data';
+ const STORE_URL = 'https://store.themeisle.com/';
+
/**
*Action used for fetching specific users/roles for permissions.
*/
diff --git a/classes/Visualizer/Render/Library.php b/classes/Visualizer/Render/Library.php
index 6263ef64..1c61c5cc 100644
--- a/classes/Visualizer/Render/Library.php
+++ b/classes/Visualizer/Render/Library.php
@@ -206,7 +206,55 @@ private function getDisplayForm() {
';
}
+ /**
+ * Renders pro charts blocker.
+ *
+ * @access private
+ */
+ private function _renderProPopupBlocker() {
+ if ( Visualizer_Module::is_pro() ) {
+ return;
+ }
+ $license = get_option( 'visualizer_pro_license_data', 'free' );
+ $license_key = '';
+ $download_id = '';
+ if ( ! empty( $license ) && is_object( $license ) ) {
+ $license_key = $license->key;
+ $download_id = $license->download_id;
+ }
+ $admin_license_url = admin_url( 'options-general.php#visualizer_pro_license' );
+ $renew_license_url = tsdk_utmify( Visualizer_Plugin::STORE_URL . '?edd_license_key=' . $license_key . '&download_id=' . $download_id, 'visualizer_license_block' );
+ echo '
+
';
echo '
';
$this->getDisplayForm();
diff --git a/css/library.css b/css/library.css
index 5fdd3c07..81017ca3 100644
--- a/css/library.css
+++ b/css/library.css
@@ -522,6 +522,7 @@ div#visualizer-types ul, div#visualizer-types form p {
.vizualizer-renew-notice-overlay {
+ display: none;
position: fixed;
top: 0;
left: 0;
@@ -532,7 +533,7 @@ div#visualizer-types ul, div#visualizer-types form p {
}
.vizualizer-renew-notice-popup {
- display: block;
+ display: none;
position: fixed;
top: 50%;
left: 50%;
@@ -594,8 +595,17 @@ div#visualizer-types ul, div#visualizer-types form p {
.vizualizer-renew-notice-close-icon {
position: absolute;
- top: 10px;
- right: 10px;
+ top: -10px;
+ right: -70px;
cursor: pointer;
color: #333;
+ background: none;
+ border: none;
+ padding: 0;
+ outline: none;
+ /* Reset button styles */
+ display: inline-block;
+ font: inherit;
+ text-align: inherit;
+ text-decoration: none;
}
diff --git a/js/library.js b/js/library.js
index 4718d915..d0efddd1 100644
--- a/js/library.js
+++ b/js/library.js
@@ -33,63 +33,13 @@
});
})(wp.media.view);
-function createPopupProBlocker() {
-
- var link = document.createElement('link');
- link.rel = 'stylesheet';
- link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css';
- document.head.appendChild(link);
-
- var overlay = document.createElement('div');
- overlay.classList.add('vizualizer-renew-notice-overlay');
- overlay.id = 'overlay-visualizer';
- document.body.appendChild(overlay);
-
- var popup = document.createElement('div');
- popup.classList.add('vizualizer-renew-notice-popup');
-
- var closeIcon = document.createElement('i');
- closeIcon.classList.add('fas', 'fa-times', 'vizualizer-renew-notice-close-icon');
- closeIcon.addEventListener('click', function() {
- document.body.removeChild(overlay);
- popup.style.display = 'none';
- });
- popup.appendChild(closeIcon);
-
- var heading = document.createElement('h1');
- heading.textContent = 'Alert!';
- heading.classList.add('vizualizer-renew-notice-heading');
- popup.appendChild(heading);
-
- var message = document.createElement('p');
- message.textContent = 'In order to edit premium charts, benefit from updates and support for Visualizer Premium plugin, please renew your license code or activate it.';
- message.classList.add('vizualizer-renew-notice-message');
- popup.appendChild(message);
-
- var buttonsContainer = document.createElement('div');
- buttonsContainer.classList.add('vizualizer-renew-notice-buttons-container');
-
- var link1 = document.createElement('a');
- link1.href = 'https://store.themeisle.com/';
- link1.target = '_blank';
- var button1 = document.createElement('button');
- button1.innerHTML = '
Renew License';
- button1.classList.add('vizualizer-renew-notice-button', 'vizualizer-renew-notice-renew-button');
- link1.appendChild(button1);
- buttonsContainer.appendChild(link1);
-
- var link2 = document.createElement('a');
- link2.href = '/wp-admin/options-general.php#visualizer_pro_license';
- var button2 = document.createElement('button');
- button2.innerHTML = '
Activate License';
- button2.classList.add('vizualizer-renew-notice-button', 'vizualizer-renew-notice-activate-button');
- link2.appendChild(button2);
- buttonsContainer.appendChild(link2);
-
- popup.appendChild(buttonsContainer);
-
- document.body.appendChild(popup);
-
+function createPopupProBlocker( $ , e ) {
+ if ( ! visualizer.is_pro_user && e.target.classList.contains('viz-is-pro-chart') ) {
+ $("#overlay-visualizer").css("display", "block");
+ $(".vizualizer-renew-notice-popup").css("display", "block");
+ return true;
+ }
+ return false;
}
(function ($, vmv, vu) {
@@ -135,12 +85,11 @@ function createPopupProBlocker() {
$(this).parent('form').submit();
});
- $('.visualizer-chart-shortcode').click(function (e) {
+ $('.visualizer-chart-shortcode').click(function (event) {
- if ( ! visualizer.is_pro_user && e.target.classList.contains('viz-is-pro-chart') ) {
- createPopupProBlocker();
- e.preventDefault();
- e.stopPropagation();
+ if ( createPopupProBlocker( $, event ) ) {
+ event.preventDefault();
+ event.stopPropagation();
return;
}
@@ -149,12 +98,12 @@ function createPopupProBlocker() {
if (window.getSelection && document.createRange) {
selection = window.getSelection();
range = document.createRange();
- range.selectNodeContents(e.target);
+ range.selectNodeContents(event.target);
selection.removeAllRanges();
selection.addRange(range);
} else if (document.selection && document.body.createTextRange) {
range = document.body.createTextRange();
- range.moveToElementText(e.target);
+ range.moveToElementText(event.target);
range.select();
}
});
@@ -195,8 +144,7 @@ function createPopupProBlocker() {
$('.visualizer-chart-edit').click(function (event) {
- if ( ! visualizer.is_pro_user && event.target.classList.contains('viz-is-pro-chart') ) {
- createPopupProBlocker();
+ if ( createPopupProBlocker( $, event ) ) {
return;
}
@@ -215,16 +163,14 @@ function createPopupProBlocker() {
return false;
});
$(".visualizer-chart-clone").on("click", function ( event ) {
- if ( ! visualizer.is_pro_user && event.target.classList.contains('viz-is-pro-chart') ) {
- createPopupProBlocker();
+ if ( createPopupProBlocker( $, event ) ) {
event.preventDefault();
}
});
$(".visualizer-chart-export").on("click", function (event) {
- if ( ! visualizer.is_pro_user && event.target.classList.contains('viz-is-pro-chart') ) {
- createPopupProBlocker();
+ if ( createPopupProBlocker( $, event ) ) {
return;
}
@@ -249,8 +195,7 @@ function createPopupProBlocker() {
});
$(".visualizer-chart-image").on("click", function (event) {
- if ( ! visualizer.is_pro_user && event.target.classList.contains('viz-is-pro-chart') ) {
- createPopupProBlocker();
+ if ( createPopupProBlocker( $, event ) ) {
return;
}
$('body').trigger('visualizer:action:specificchart', {action: 'image', id: $(this).attr("data-chart"), data: null, dataObj: {name: $(this).attr("data-chart-title")}});
diff --git a/tests/e2e/specs/upsell.spec.js b/tests/e2e/specs/upsell.spec.js
index 9e63ffb3..170b7ef7 100644
--- a/tests/e2e/specs/upsell.spec.js
+++ b/tests/e2e/specs/upsell.spec.js
@@ -9,99 +9,125 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
const { deleteAllCharts, getAssetFilePath, CHART_JS_LABELS, selectChartAdmin } = require('../utils/common');
test.describe( 'Upsell', () => {
- test.beforeEach( async ( { admin, requestUtils, page } ) => {
- await deleteAllCharts( requestUtils );
- await admin.visitAdminPage( 'admin.php?page=visualizer' );
- page.setDefaultTimeout( 5000 );
- } );
-
- test( 'chart selection on admin', async ( { admin, page } ) => {
- await admin.visitAdminPage( 'admin.php?page=visualizer&vaction=addnew' );
- await page.waitForURL( '**/admin.php?page=visualizer&vaction=addnew' );
- await page.waitForSelector('h1:text("Visualizer")');
-
- expect( await page.frameLocator('iframe').locator('.pro-upsell').count() ).toBe( 11 );
-
- const proUpsellElements = await page.frameLocator('iframe').locator('a.pro-upsell').all();
-
- for (const element of proUpsellElements) {
- const href = await element.getAttribute('href');
- const searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('charttypes');
- }
- } );
-
- test( 'chart settings on admin', async ( { admin, page } ) => {
- await admin.visitAdminPage( 'admin.php?page=visualizer&vaction=addnew' );
- await page.waitForURL( '**/admin.php?page=visualizer&vaction=addnew' );
- await page.waitForSelector('h1:text("Visualizer")');
- await selectChartAdmin( page.frameLocator('iframe'), CHART_JS_LABELS.pie );
-
- await expect( page.frameLocator('iframe').locator( '#viz-tabs' ) ).toBeVisible();
-
- expect( await page.frameLocator('iframe').locator('#vz-chart-source .viz-group-title .dashicons-lock').count() ).toBe( 5 );
-
-
- const uploadFileUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_csv .only-pro-inner a');
- let href = await uploadFileUpsell.getAttribute('href');
- let searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('import-file');
-
- const remoteImportUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_json .only-pro-inner a').first();
- href = await remoteImportUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('import-url');
-
- const otherChartUpsell = page.frameLocator('iframe').locator('#vz-chart-source .viz-import-from-other .only-pro-inner a');
- href = await otherChartUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('import-chart');
-
- const wpImportUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_query_wp .only-pro-inner a');
- href = await wpImportUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('import-wp');
- await page.frameLocator('iframe').getByRole('heading', { name: /Import from WordPress/ }).click();
- await expect(page.frameLocator('iframe').locator('#vz-chart-source')).toContainText('Upgrade to PRO to activate this feature!');
-
- const dbImportUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_query .only-pro-inner a');
- href = await dbImportUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('db-query');
-
- await page.frameLocator('iframe').getByRole('heading', { name: /Import from database/ }).click();
- await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade to Plus plan to activate this feature!');
- await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade Now');
-
- await page.frameLocator('iframe').getByRole('link', { name: 'Settings' }).click();
-
- const dataFilterConfigurationUpsell = page.frameLocator('iframe').locator('#vz-data-controls .only-pro-inner a');
- href = await dataFilterConfigurationUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('data-filter-configuration');
-
- const frontendActionsUpsell = page.frameLocator('iframe').locator('#vz-frontend-actions .only-pro-inner a');
- href = await frontendActionsUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('frontend-actions');
-
- const chartPermissionsUpsell = page.frameLocator('iframe').locator('#vz-permissions .only-pro-inner a');
- href = await chartPermissionsUpsell.getAttribute('href');
- searchParams = new URLSearchParams(href);
- expect( searchParams.get('utm_campaign') ).toBe('chart-permissions');
- await page.frameLocator('iframe').getByRole('heading', { name: /Permissions/ }).click();
- await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade to Plus plan to activate this feature!');
- await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade Now');
- });
-
- test( 'featured tab in Install Plugin (SDK)', async ( { admin, page } ) => {
- await admin.visitAdminPage( 'plugin-install.php' );
-
- // Those should be visible only when a PRO product is installed.
- await expect( page.getByText('Image Optimization by Optimole') ).toBeHidden();
- await expect( page.locator('#the-list div').filter({ hasText: 'Otter Blocks' }).nth(1) ).toBeHidden();
-
- await expect( page.getByLabel('Install Image Optimization by') ).toBeHidden();
- await expect( page.getByLabel('Install Otter Blocks') ).toBeHidden();
- });
+ test.beforeEach( async ( { admin, requestUtils, page } ) => {
+ await deleteAllCharts( requestUtils );
+ await admin.visitAdminPage( 'admin.php?page=visualizer' );
+ page.setDefaultTimeout( 5000 );
+ } );
+
+ test( 'chart selection on admin', async ( { admin, page } ) => {
+ await admin.visitAdminPage( 'admin.php?page=visualizer&vaction=addnew' );
+ await page.waitForURL( '**/admin.php?page=visualizer&vaction=addnew' );
+ await page.waitForSelector('h1:text("Visualizer")');
+
+ expect( await page.frameLocator('iframe').locator('.pro-upsell').count() ).toBe( 11 );
+
+ const proUpsellElements = await page.frameLocator('iframe').locator('a.pro-upsell').all();
+
+ for (const element of proUpsellElements) {
+ const href = await element.getAttribute('href');
+ const searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('charttypes');
+ }
+ } );
+
+ test( 'chart settings on admin', async ( { admin, page } ) => {
+ await admin.visitAdminPage( 'admin.php?page=visualizer&vaction=addnew' );
+ await page.waitForURL( '**/admin.php?page=visualizer&vaction=addnew' );
+ await page.waitForSelector('h1:text("Visualizer")');
+ await selectChartAdmin( page.frameLocator('iframe'), CHART_JS_LABELS.pie );
+
+ await expect( page.frameLocator('iframe').locator( '#viz-tabs' ) ).toBeVisible();
+
+ expect( await page.frameLocator('iframe').locator('#vz-chart-source .viz-group-title .dashicons-lock').count() ).toBe( 5 );
+
+
+ const uploadFileUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_csv .only-pro-inner a');
+ let href = await uploadFileUpsell.getAttribute('href');
+ let searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('import-file');
+
+ const remoteImportUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_json .only-pro-inner a').first();
+ href = await remoteImportUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('import-url');
+
+ const otherChartUpsell = page.frameLocator('iframe').locator('#vz-chart-source .viz-import-from-other .only-pro-inner a');
+ href = await otherChartUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('import-chart');
+
+ const wpImportUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_query_wp .only-pro-inner a');
+ href = await wpImportUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('import-wp');
+ await page.frameLocator('iframe').getByRole('heading', { name: /Import from WordPress/ }).click();
+ await expect(page.frameLocator('iframe').locator('#vz-chart-source')).toContainText('Upgrade to PRO to activate this feature!');
+
+ const dbImportUpsell = page.frameLocator('iframe').locator('#vz-chart-source .visualizer_source_query .only-pro-inner a');
+ href = await dbImportUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('db-query');
+
+ await page.frameLocator('iframe').getByRole('heading', { name: /Import from database/ }).click();
+ await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade to Plus plan to activate this feature!');
+ await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade Now');
+
+ await page.frameLocator('iframe').getByRole('link', { name: 'Settings' }).click();
+
+ const dataFilterConfigurationUpsell = page.frameLocator('iframe').locator('#vz-data-controls .only-pro-inner a');
+ href = await dataFilterConfigurationUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('data-filter-configuration');
+
+ const frontendActionsUpsell = page.frameLocator('iframe').locator('#vz-frontend-actions .only-pro-inner a');
+ href = await frontendActionsUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('frontend-actions');
+
+ const chartPermissionsUpsell = page.frameLocator('iframe').locator('#vz-permissions .only-pro-inner a');
+ href = await chartPermissionsUpsell.getAttribute('href');
+ searchParams = new URLSearchParams(href);
+ expect( searchParams.get('utm_campaign') ).toBe('chart-permissions');
+ await page.frameLocator('iframe').getByRole('heading', { name: /Permissions/ }).click();
+ await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade to Plus plan to activate this feature!');
+ await expect(page.frameLocator('iframe').locator('#vz-db-wizard')).toContainText('Upgrade Now');
+ });
+
+ test( 'featured tab in Install Plugin (SDK)', async ( { admin, page } ) => {
+ await admin.visitAdminPage( 'plugin-install.php' );
+
+ // Those should be visible only when a PRO product is installed.
+ await expect( page.getByText('Image Optimization by Optimole') ).toBeHidden();
+ await expect( page.locator('#the-list div').filter({ hasText: 'Otter Blocks' }).nth(1) ).toBeHidden();
+
+ await expect( page.getByLabel('Install Image Optimization by') ).toBeHidden();
+ await expect( page.getByLabel('Install Otter Blocks') ).toBeHidden();
+ });
+
+ test( 'pro chart license lock', async ( { admin, page } ) => {
+ await admin.visitAdminPage('admin.php?page=visualizer');
+ await page.waitForURL('**/admin.php?page=visualizer');
+
+ // Check if the popup HTML is present
+ const popupSelector = '.vizualizer-renew-notice-popup';
+ const popup = await page.$(popupSelector);
+ expect(popup).not.toBeNull();
+
+ const heading = await page.$('h1.vizualizer-renew-notice-heading');
+ expect(heading).not.toBeNull();
+
+ const message = await page.$('p.vizualizer-renew-notice-message');
+ expect(message).not.toBeNull();
+
+ const renewButton = await page.$('button.vizualizer-renew-notice-renew-button');
+ expect(renewButton).not.toBeNull();
+
+ const activateButton = await page.$('button.vizualizer-renew-notice-activate-button');
+ expect(activateButton).not.toBeNull();
+
+ const closeButton = await page.$('button.vizualizer-renew-notice-close-icon');
+ expect(closeButton).not.toBeNull();
+ });
+
} );