diff --git a/css/settings.css b/css/settings.css index 84af6c2b3..4a0719360 100644 --- a/css/settings.css +++ b/css/settings.css @@ -2512,7 +2512,7 @@ li.draggable-item .components-panel__body-toggle.components-button{ padding: 24px 0; } -.fz-condition-control.is-upsell { +.is-upsell { opacity: 0.6; } diff --git a/includes/admin/feedzy-rss-feeds-admin.php b/includes/admin/feedzy-rss-feeds-admin.php index 9b87e51ac..a0b4ae184 100644 --- a/includes/admin/feedzy-rss-feeds-admin.php +++ b/includes/admin/feedzy-rss-feeds-admin.php @@ -485,6 +485,7 @@ function closeModal(e) { jQuery(document).on('keyup', function (e) { if (e.key === "Escape") closeModal(); }); + }); -
+
@@ -119,9 +119,6 @@ class="dashicons dashicons-arrow-down-alt2">
- - -
@@ -630,15 +627,14 @@ class="fz-switch-toggle" type="checkbox" value="yes" -
- +
-

PRO' : ''; ?>

+

- @@ -674,11 +671,10 @@ class="fz-switch-toggle" type="checkbox" value="yes"
-
- +

- PRO' : ''; ?> +

diff --git a/js/Conditions/ConditionsControl.js b/js/Conditions/ConditionsControl.js index 14406d3a6..fb8b7a15a 100644 --- a/js/Conditions/ConditionsControl.js +++ b/js/Conditions/ConditionsControl.js @@ -6,11 +6,10 @@ import classNames from 'classnames'; /** * WordPress dependencies. */ -import { __ } from '@wordpress/i18n'; - +import { __, sprintf } from '@wordpress/i18n'; import { Button, SelectControl, TextControl } from '@wordpress/components'; - import { Icon, plus } from '@wordpress/icons'; +import { useState } from '@wordpress/element'; /** * Internal dependencies. @@ -18,6 +17,7 @@ import { Icon, plus } from '@wordpress/icons'; import PanelTab from './PanelTab'; import DateTimeControl from './DateTimeControl'; +const isPro = window.feedzyData.isPro; const SUPPORTED_FIELDS = [ { label: __('Title', 'feedzy-rss-feeds'), @@ -26,15 +26,18 @@ const SUPPORTED_FIELDS = [ { label: __('Description', 'feedzy-rss-feeds'), value: 'description', + disabled: !isPro, }, { label: __('Full Content', 'feedzy-rss-feeds'), value: 'fullcontent', + disabled: !isPro, }, { label: __('Author', 'feedzy-rss-feeds'), value: 'author', unsupportedOperators: ['greater_than', 'gte', 'less_than', 'lte'], + disabled: !isPro, }, { label: __('Date', 'feedzy-rss-feeds'), @@ -47,21 +50,24 @@ const SUPPORTED_FIELDS = [ 'contains', 'not_contains', ], + disabled: !isPro, }, { label: __('Featured Image', 'feedzy-rss-feeds'), value: 'featured_image', unsupportedOperators: ['greater_than', 'gte', 'less_than', 'lte'], + disabled: !isPro, }, { label: __('Link', 'feedzy-rss-feeds'), value: 'link', unsupportedOperators: ['greater_than', 'gte', 'less_than', 'lte'], + disabled: !isPro, }, ]; -const isPro = window.feedzyData.isPro; const ConditionsControl = ({ conditions, setConditions }) => { + const [modalOpen, setModelOpen] = useState(false); const onChangeMatch = (value) => { setConditions({ ...conditions, @@ -69,7 +75,18 @@ const ConditionsControl = ({ conditions, setConditions }) => { }); }; + const el = document.querySelector('.editor-sidebar__panel-tabs'); const addCondition = () => { + if (!isPro && 1 <= conditions.conditions.length) { + // the Inspector panel use sticky position with their own stacking context, + // which causes them to appear above our popup overlay. We set their z-index to 0 so the popup covers them. + if (el) { + el.style.zIndex = 0; + } + setModelOpen(true); + return; + } + const conditionsCopy = [...conditions.conditions]; conditionsCopy.push({ @@ -120,128 +137,220 @@ const ConditionsControl = ({ conditions, setConditions }) => { }); }; + const closeModal = () => { + if (el) { + el.style.zIndex = 0; + } + setModelOpen(false); + }; + return ( -
- - - {conditions.conditions.map((condition, index) => { - const field = SUPPORTED_FIELDS.find( - (i) => i.value === condition.field - ); - const operators = Object.keys( - window?.feedzyConditionsData?.operators - ).filter((key) => !field?.unsupportedOperators?.includes(key)); - - return ( - removeCondition(index)} - initialOpen={index === 0} - > - - onChangeCondition(index, value, 'field') - } - disabled={!isPro} - /> - - ({ - label: window.feedzyConditionsData.operators[ - key - ], - value: key, - }))} - help={ - ['contains', 'not_contains'].includes( - condition?.operator - ) - ? __( - 'You can use comma(,) and plus(+) keyword.', - 'feedzy-rss-feeds' - ) - : '' - } - value={condition?.operator} - onChange={(value) => - onChangeCondition(index, value, 'operator') - } - disabled={!isPro} - /> - - {!['has_value', 'empty'].includes( - condition?.operator - ) && ( - <> - {condition?.field === 'date' ? ( - - onChangeCondition( - index, - value, - 'value' - ) - } - disabled={!isPro} - /> - ) : ( - - onChangeCondition( - index, - value, - 'value' - ) - } - disabled={!isPro} - /> + <> +
+ + + {conditions.conditions.map((condition, index) => { + const field = SUPPORTED_FIELDS.find( + (i) => i.value === condition.field + ); + const operators = Object.keys( + window?.feedzyConditionsData?.operators + ).filter( + (key) => !field?.unsupportedOperators?.includes(key) + ); + + return ( + removeCondition(index)} + initialOpen={index === 0} + > + + onChangeCondition(index, value, 'field') + } + /> + + - )} - - ); - })} - -
- + +
-
+ {modalOpen && ( +
+
+ +
+

+ {__( + 'Upgrade to Use Unlimited Conditions', + 'feedzy-rss-feeds' + )} +

+

+ {__( + 'Filter Condition limit reached', + 'feedzy-rss-feeds' + )} + + {'(' + + sprintf( + // translators: %1$s is the number of imports used, %2$s is the total number of imports allowed. + __( + '%1$s/%2$s used', + 'feedzy-rss-feeds' + ), + '1', + '1' + ) + + ')'} + +

+
+
+

+ {__( + "Your current plan supports only one filter condition. Upgrade to unlock unlimited import configurations and make the most of Feedzy's powerful features!", + 'feedzy-rss-feeds' + )} +

+
+
+ + + {__( + '30-day money-back guarantee. No questions asked.', + 'feedzy-rss-feeds' + )} + +
+
+
+ )} + ); }; diff --git a/js/Conditions/index.js b/js/Conditions/index.js index db5b5c97a..4fb7ef013 100644 --- a/js/Conditions/index.js +++ b/js/Conditions/index.js @@ -28,11 +28,6 @@ const App = () => { }); useEffect(() => { - if (!feedzyData.isPro) { - setConditions(dummyConditions); - return; - } - const field = document.getElementById('feed-post-filters-conditions'); if (field && field.value) { const parsedConditions = JSON.parse(field.value); @@ -45,10 +40,6 @@ const App = () => { }, []); useEffect(() => { - if (!feedzyData.isPro) { - return; - } - document.getElementById('feed-post-filters-conditions').value = JSON.stringify(conditions); }, [conditions]); diff --git a/js/FeedzyBlock/inspector.js b/js/FeedzyBlock/inspector.js index 7c25b0244..f3716399e 100644 --- a/js/FeedzyBlock/inspector.js +++ b/js/FeedzyBlock/inspector.js @@ -258,21 +258,14 @@ class Inspector extends Component { Pro - ), ]} initialOpen={false} - className={ - window.feedzyjs.isPro - ? 'feedzy-item-filter' - : 'feedzy-item-filter fz-locked' - } + className='feedzy-item-filter' > {!window.feedzyjs.isPro && (
{__( - 'Unlock this feature and more advanced options with', + 'Unlock more advanced options with', 'feedzy-rss-feeds' )}{' '} @@ -307,6 +300,7 @@ class Inspector extends Component { { label: __('Author', 'feedzy-rss-feeds'), value: 'author', + disabled: !window.feedzyjs.isPro, }, { label: __( @@ -314,6 +308,7 @@ class Inspector extends Component { 'feedzy-rss-feeds' ), value: 'description', + disabled: !window.feedzyjs.isPro, }, ]} onChange={this.props.edit.onKeywordsIncludeOn} @@ -345,6 +340,7 @@ class Inspector extends Component { { label: __('Author', 'feedzy-rss-feeds'), value: 'author', + disabled: !window.feedzyjs.isPro, }, { label: __( @@ -352,28 +348,37 @@ class Inspector extends Component { 'feedzy-rss-feeds' ), value: 'description', + disabled: !window.feedzyjs.isPro, }, ]} onChange={this.props.edit.onKeywordsExcludeOn} /> -

- {__( - 'Filter feed item by date range.', - 'feedzy-rss-feeds' - )} -

- - + +
+

+ {__( + 'Filter feed item by date range.', + 'feedzy-rss-feeds' + )} +

+ + +
)} diff --git a/js/FeedzyLoop/controls.js b/js/FeedzyLoop/controls.js index 34abfc9e9..c28bb5fe6 100644 --- a/js/FeedzyLoop/controls.js +++ b/js/FeedzyLoop/controls.js @@ -195,9 +195,6 @@ const Controls = ({ Pro - ), ]} initialOpen={false} key="filters" @@ -206,7 +203,7 @@ const Controls = ({ {!window.feedzyData.isPro && (
{__( - 'Unlock this feature and more advanced options with', + 'Unlock more advanced options with', 'feedzy-rss-feeds' )}{' '} @@ -222,7 +219,7 @@ const Controls = ({ conditions: [], match: 'all', } - : { + : attributes?.conditions || { match: 'all', conditions: [ { diff --git a/js/FeedzyLoop/editor.scss b/js/FeedzyLoop/editor.scss index c37cd05e9..d5bd46085 100644 --- a/js/FeedzyLoop/editor.scss +++ b/js/FeedzyLoop/editor.scss @@ -13,10 +13,6 @@ .fz-condition-control { padding: 0; - &.is-upsell { - opacity: 0.6; - } - .components-button { width: 100%; margin: 0; @@ -25,6 +21,10 @@ } } +.is-upsell { + opacity: 0.6; +} + .fz-panel-tab { z-index: 999999; margin: 24px 0; diff --git a/tests/e2e/specs/upsell.spec.js b/tests/e2e/specs/upsell.spec.js index f8204412f..386dea273 100644 --- a/tests/e2e/specs/upsell.spec.js +++ b/tests/e2e/specs/upsell.spec.js @@ -20,8 +20,9 @@ test.describe( 'Upsell', () => { // Hover over text named Filter by Keyword const filtersTab = page.locator('#feedzy-import-form > div.feedzy-accordion > div:nth-child(2)'); - // It should have 1 elements with .only-pro-content class. - await expect( filtersTab.locator('.pro-label').count() ).resolves.toBe(1); + await page.locator('.fz-action-btn').click(); + // 'Add condition' action button has .is-upsell class. + await expect(filtersTab.locator('.fz-action-btn.is-upsell')).toHaveCount(1); } ); @@ -29,22 +30,21 @@ test.describe( 'Upsell', () => { test( 'general settings', async({ editor, page }) => { await page.getByRole('button', { name: 'Step 4 General feed settings' }).click({ force: true }); + await page.locator('.fz-form-group:has( #fz-event-schedule )').scrollIntoViewIfNeeded() + // check all the option expect daily is disabled. + const otherOptions = page.locator('#fz-event-schedule option:not([value="daily"])'); + const count = await otherOptions.count(); - await page.locator('.fz-form-group:has( #feed-post-default-thumbnail )').hover({ force: true }); - let upgradeAlert = page.locator('#feedzy-import-form a[href*="utm_campaign=fallback-image"]'); - await expect( upgradeAlert ).toBeVisible(); - - await page.locator('.fz-form-group:has( #fz-event-schedule )').scrollIntoViewIfNeeded() - await page.locator('.fz-form-group:has( #fz-event-schedule )').hover({ force: true }); - upgradeAlert = page.locator('#feedzy-import-form a[href*="utm_campaign=schedule-import-job"]'); - await expect( upgradeAlert ).toBeVisible(); + for (let i = 0; i < count; i++) { + await expect(otherOptions.nth(i)).toBeDisabled(); + } // Click the advanced settings tab. await page.click('[data-id="fz-advanced-settings"]'); await page.locator('.fz-form-group:has( #feedzy_mark_duplicate )').hover({ force: true }); - upgradeAlert = page.locator('#feedzy-import-form a[href*="utm_campaign=remove-duplicates"]'); + const upgradeAlert = page.locator('#feedzy-import-form a[href*="utm_campaign=remove-duplicates"]'); await expect( upgradeAlert ).toBeVisible(); } ); });