Skip to content

Commit 3bc227f

Browse files
feat: add offload restrictions (#968)
- Start the revert process if the grace period has ended for people who are now in a plan that does not support offloading. - Show notice for older free users about the change in Offloading if they have it enabled. - Show upgrade message in the Offloading modal on plans without Offloading.
1 parent 3d48b2b commit 3bc227f

File tree

6 files changed

+86
-17
lines changed

6 files changed

+86
-17
lines changed

assets/src/dashboard/parts/components/Modal.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { close } from '@wordpress/icons';
44
import { useViewportMatch } from '@wordpress/compose';
55
import { Button, Icon, Modal as CoreModal } from '@wordpress/components';
66

7-
export default function Modal({ icon, labels = {}, onRequestClose = () => {}, onConfirm = () => {}, variant = 'default', onSecondaryAction = () => {} }) {
7+
export default function Modal({ icon, labels = {}, onRequestClose = () => {}, onConfirm = () => {}, variant = 'default', onSecondaryAction = () => {}, afterContentChildren = null }) {
88

99
const isMobileViewport = useViewportMatch( 'small', '<' );
1010

@@ -53,7 +53,8 @@ export default function Modal({ icon, labels = {}, onRequestClose = () => {}, on
5353
className="text-center mx-0 my-4 text-gray-700"
5454
dangerouslySetInnerHTML={ { __html: labels.description } }
5555
/>
56-
<div class="flex gap-4">
56+
{ afterContentChildren }
57+
<div className="flex gap-4">
5758
<Button variant="primary" className={ actionButtonClasses } onClick={ onConfirm }>
5859
{ labels.action }
5960
</Button>

assets/src/dashboard/parts/connected/settings/OffloadMedia.js

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* global optimoleDashboardApp */
22

33
import classnames from 'classnames';
4-
import { useEffect, useState } from '@wordpress/element';
4+
import { useEffect, useState, useMemo } from '@wordpress/element';
55
import { useDispatch, useSelect } from '@wordpress/data';
66
import { Icon } from '@wordpress/icons';
77

@@ -37,7 +37,9 @@ const OffloadMedia = ({ settings, canSave, setSettings, setCanSave }) => {
3737
processedImages,
3838
offloadFinishNotice,
3939
offloadLimitReached,
40-
offloadLimit
40+
offloadLimit,
41+
canUseMediaOffloadingFlag,
42+
canShowFreeUserWithOffloadNoticeFlag
4143
} = useSelect( select => {
4244
const {
4345
getOffloadConflicts,
@@ -51,9 +53,13 @@ const OffloadMedia = ({ settings, canSave, setSettings, setCanSave }) => {
5153
getQueryArgs,
5254
isLoading,
5355
getSiteSettings,
54-
getOffloadLimit
56+
getOffloadLimit,
57+
getUserData,
58+
canShowFreeUserWithOffloadNotice
5559
} = select( 'optimole' );
5660

61+
const userData = getUserData();
62+
5763
return {
5864
offloadConflicts: getOffloadConflicts(),
5965
errorMedia: getErrorMedia(),
@@ -67,7 +73,9 @@ const OffloadMedia = ({ settings, canSave, setSettings, setCanSave }) => {
6773
processedImages: getProcessedImages(),
6874
offloadFinishNotice: getSiteSettings( 'show_offload_finish_notice' ),
6975
offloadLimitReached: 'enabled' === getSiteSettings( 'offload_limit_reached' ),
70-
offloadLimit: getOffloadLimit()
76+
offloadLimit: getOffloadLimit(),
77+
canUseMediaOffloadingFlag: Boolean( userData?.can_use_offloading ),
78+
canShowFreeUserWithOffloadNoticeFlag: canShowFreeUserWithOffloadNotice()
7179
};
7280
}, []);
7381

@@ -85,6 +93,9 @@ const OffloadMedia = ({ settings, canSave, setSettings, setCanSave }) => {
8593
const isOffloadingInProgress = 'disabled' !== settings['offloading_status'];
8694
const isRollbackInProgress = 'disabled' !== settings['rollback_status'];
8795

96+
const showDisabledOffloadingNotice = useMemo( () => {
97+
return 'enabled' === settings?.['offload_media'] && ! canUseMediaOffloadingFlag && canShowFreeUserWithOffloadNoticeFlag;
98+
}, [ settings, canUseMediaOffloadingFlag, canShowFreeUserWithOffloadNoticeFlag ]);
8899

89100
useEffect( () => {
90101
if ( isOffloadingInProgress ) {
@@ -187,18 +198,28 @@ const OffloadMedia = ({ settings, canSave, setSettings, setCanSave }) => {
187198
[MODAL_STATE_OFFLOAD]: {
188199
icon: offload,
189200
onConfirm: () => {
190-
nextSettings['offload_media'] = 'offload' === optionValue ? 'enabled' : 'disabled';
191-
setSettings( nextSettings );
192-
setCanSave( true );
193-
194-
onOffloadMedia();
201+
if ( canUseMediaOffloadingFlag ) {
202+
nextSettings['offload_media'] = 'offload' === optionValue ? 'enabled' : 'disabled';
203+
setSettings( nextSettings );
204+
setCanSave( true );
205+
206+
onOffloadMedia();
207+
} else {
208+
window.open( optimoleDashboardApp?.offload_upgrade_url, '_blank' );
209+
}
195210
setModal( null );
196211
},
197212
labels: {
198213
title: options_strings.offloading_start_title,
199214
description: options_strings.offloading_start_description,
200-
action: options_strings.offloading_start_action
201-
}
215+
action: canUseMediaOffloadingFlag ? options_strings.offloading_start_action : optimoleDashboardApp.strings.upgrade.title_long
216+
},
217+
afterContentChildren: ! canUseMediaOffloadingFlag && (
218+
<Notice
219+
type="warning"
220+
text={options_strings.upgrade_to_use_offloading_notice_desc}
221+
/>
222+
)
202223
},
203224
[MODAL_STATE_ROLLBACK]: {
204225
icon: rollbackIcon,
@@ -322,6 +343,16 @@ const OffloadMedia = ({ settings, canSave, setSettings, setCanSave }) => {
322343
<h1 className="text-xl font-bold">{options_strings.enable_offload_media_title}</h1>
323344
<p dangerouslySetInnerHTML={{ __html: options_strings.enable_offload_media_desc }}/>
324345

346+
{
347+
showDisabledOffloadingNotice && (
348+
<Notice
349+
type="warning"
350+
title={options_strings.plan_update_notice_title}
351+
text={options_strings.plan_update_notice_desc}
352+
/>
353+
)
354+
}
355+
325356
{offloadFinishNotice && (
326357
<Notice
327358
title={'offload' === offloadFinishNotice ? options_strings.offloading_success : options_strings.rollback_success }

assets/src/dashboard/store/reducer.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ const DEFAULT_STATE = {
3131
logs: {
3232
offload: '',
3333
rollback: ''
34-
}
34+
},
35+
canShowFreeUserWithOffloadNotice: 'yes' === optimoleDashboardApp?.show_free_user_with_offload_notice
3536
};
3637

3738
const reducer = ( state = DEFAULT_STATE, action ) => {

assets/src/dashboard/store/selectors.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ const selectors = {
9696
},
9797
isSubApiKey( state ) {
9898
return state.apiKey && state.apiKey.startsWith( 'optml-s' );
99+
},
100+
canShowFreeUserWithOffloadNotice( state ) {
101+
return Boolean( state?.canShowFreeUserWithOffloadNotice );
99102
}
100103
};
101104

inc/admin.php

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ public function __construct() {
113113
}
114114

115115
add_filter( 'themeisle-sdk/survey/' . OPTML_PRODUCT_SLUG, [ $this, 'get_survey_metadata' ], 10, 2 );
116+
add_action( 'admin_init', [ $this, 'mark_user_with_offload' ] );
116117
}
117118

118119
/**
@@ -1068,8 +1069,16 @@ public function daily_sync() {
10681069
if ( isset( $data['extra_visits'] ) ) {
10691070
$this->settings->update_frontend_banner_from_remote( $data['extra_visits'] );
10701071
}
1072+
10711073
// Here the account got deactivated, in this case we check if the user is using offloaded images and we roll them back.
1072-
if ( isset( $data['status'] ) && $data['status'] === 'inactive' ) {
1074+
$should_revert_offloading = isset( $data['status'] ) && $data['status'] === 'inactive';
1075+
1076+
// The user is now on a plan without offloading and the grace period is over.
1077+
if ( isset( $data['should_revert_offload'] ) && (bool) $data['should_revert_offload'] ) {
1078+
$should_revert_offloading = true;
1079+
}
1080+
1081+
if ( $should_revert_offloading ) {
10731082
// We check if the user has images offloaded.
10741083
if ( $this->settings->get( 'offload_media' ) === 'disabled' ) {
10751084
return;
@@ -1373,6 +1382,7 @@ private function localize_dashboard_app() {
13731382
'optimoleHome' => tsdk_translate_link( 'https://optimole.com/' ),
13741383
'optimoleDashHome' => tsdk_translate_link( 'https://dashboard.optimole.com/', 'query' ),
13751384
'optimoleDashBilling' => tsdk_translate_link( 'https://dashboard.optimole.com/settings/billing', 'query' ),
1385+
'offload_upgrade_url' => tsdk_translate_link( tsdk_utmify( 'https://optimole.com/pricing/', 'offload' ) ),
13761386
'days_since_install' => round( ( time() - get_option( 'optimole_wp_install', 0 ) ) / DAY_IN_SECONDS ),
13771387
'is_offload_media_available' => $is_offload_media_available,
13781388
'auto_connect' => $auto_connect,
@@ -1387,6 +1397,7 @@ private function localize_dashboard_app() {
13871397
'bf_notices' => $this->get_bf_notices(),
13881398
'spc_banner' => $this->get_spc_banner(),
13891399
'show_exceed_plan_quota_notice' => $this->should_show_exceed_quota_warning(),
1400+
'show_free_user_with_offload_notice' => get_option( 'optml_has_offloading_enabled_on_upgrade', 'no' ),
13901401
'report_issue_url' => add_query_arg(
13911402
[
13921403
'utm_source' => 'plugin',
@@ -1624,7 +1635,7 @@ private function get_dashboard_strings() {
16241635
' <a href="' . esc_url( tsdk_translate_link( 'https://dashboard.optimole.com/register', 'query' ) ) . '" target="_blank">optimole.com</a>'
16251636
),
16261637
'account_needed_subtitle_1' => sprintf(
1627-
/* translators: 1 is starting bold tag, 2 is ending bold tag, 3 is the starting bold tag, 4 is the limit number, 5 is ending bold tag, 6 is the starting anchor tag for the docs link on how we count visits, 7 is the ending anchor tag. */
1638+
/* translators: 1 is the starting bold tag, 2 is the ending bold tag, 3 is the starting bold tag, 4 is the limit number, 5 is ending bold tag, 6 is the starting anchor tag for the docs link on how we count visits, 7 is the ending anchor tag. */
16281639
__( '%1$sOptimize unlimited images%2$s for up to %3$s monthly %4$svisitors%5$s - completely FREE.', 'optimole-wp' ),
16291640
'<strong>',
16301641
'</strong>',
@@ -2083,6 +2094,9 @@ private function get_dashboard_strings() {
20832094
'exceed_plan_quota_notice_description' => sprintf( /* translators: 1 is the starting anchor tag, 2 is the ending anchor tag */ __( 'Based on this trend, you are likely to exceed your free quota before the month ends. To avoid any disruption in service, we strongly recommend %1$supgrading%2$s your plan or waiting until your traffic stabilizes before offloading your images. Do you still wish to proceed?', 'optimole-wp' ), '<a style="white-space: nowrap;" target=”_blank” href="https://dashboard.optimole.com/settings/billing/">', '</a>' ),
20842095
'exceed_plan_quota_notice_start_action' => __( 'Yes, Transfer to Optimole Cloud', 'optimole-wp' ),
20852096
'exceed_plan_quota_notice_secondary_action' => __( 'No, keep images on my website', 'optimole-wp' ),
2097+
'plan_update_notice_title' => __( 'Plan Update', 'optimole-wp' ),
2098+
'plan_update_notice_desc' => __( 'We\'ve changed how plans work. Users on the Optimole Free plan cannot offload new images. Existing images that are already offloaded will remain offloaded.', 'optimole-wp' ),
2099+
'upgrade_to_use_offloading_notice_desc' => __( 'Offloading images is a PRO feature. Please upgrade your plan to enable image transfer to Optimole Cloud.', 'optimole-wp' ),
20862100
'visual_settings' => __( 'Visual Settings', 'optimole-wp' ),
20872101
'extended_features' => __( 'Extended Features', 'optimole-wp' ),
20882102
// translators: mark that the options are aplied globally.
@@ -2377,4 +2391,23 @@ private function get_active_notices_count() {
23772391

23782392
return $conflicts_count - count( $dismissed_notices );
23792393
}
2394+
2395+
/**
2396+
* Mark if the user had offloading enabled on first run.
2397+
*
2398+
* If it is an old free user that had offloading enabled, we will use the mark to show a notice about the plan changes.
2399+
*
2400+
* @return void
2401+
*/
2402+
public function mark_user_with_offload() {
2403+
if ( ! $this->settings->is_connected() ) {
2404+
return;
2405+
}
2406+
2407+
if ( false !== get_option( 'optml_has_offloading_enabled_on_upgrade', false ) ) {
2408+
return;
2409+
}
2410+
2411+
update_option( 'optml_has_offloading_enabled_on_upgrade', $this->settings->is_offload_enabled() ? 'yes' : 'no' );
2412+
}
23802413
}

inc/main.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ final class Optml_Main {
77
/**
88
* Optml_Main The single instance of Starter_Plugin.
99
*
10-
* @var object
10+
* @var Optml_Main|null
1111
* @access private
1212
* @since 1.0.0
1313
*/

0 commit comments

Comments
 (0)