PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 2.0.26
Advanced Ads – Ad Manager & AdSense v2.0.26
2.0.26 2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / src / admin / screen-licenses / components / AddonRowActions.jsx
advanced-ads / src / admin / screen-licenses / components Last commit date
AddonRowActions.jsx 4 weeks ago AddonsList.jsx 4 weeks ago AllAccessAddonsSummary.jsx 1 month ago AutoUpdateModal.jsx 1 month ago DownloadActivateButton.jsx 4 weeks ago EmptyState.jsx 1 month ago FeatureList.jsx 1 month ago LicenseField.jsx 1 month ago LicenseItem.jsx 4 weeks ago LicenseNotices.jsx 4 weeks ago LicenseStatus.jsx 1 month ago Loader.jsx 4 weeks ago PricingModal.jsx 1 month ago PricingTable.jsx 1 month ago PricingTableItem.jsx 1 month ago SitesModal.jsx 1 month ago
AddonRowActions.jsx
291 lines
1 /**
2 * WordPress Dependencies
3 */
4 import { __ } from '@wordpress/i18n';
5 import { useState } from '@wordpress/element';
6 import { useDispatch, useSelect } from '@wordpress/data';
7 import { store as noticesStore } from '@wordpress/notices';
8
9 /**
10 * External Dependencies
11 */
12 import { Check, AlertCircle, Loader2 } from 'lucide-react';
13
14 /**
15 * Internal Dependencies
16 */
17 import { STORE_NAME } from '@admin/store';
18 import { getManualInstallGuideUrl } from '../addon-catalog';
19 import {
20 activateAddonFromLicense,
21 deactivateAddonFromLicense,
22 extractApiErrorMessage,
23 } from '../hooks/licenses-api';
24 import { getAddonInstallState, getAddonRowStatus } from '../utils';
25 import { publishLicenseWarningNotice } from './LicenseNotices';
26
27 function BusyStatus( { label } ) {
28 return (
29 <span className="inline-flex items-center gap-2 text-sm text-gray-600">
30 <Loader2
31 className="size-4 shrink-0"
32 strokeWidth={ 2 }
33 aria-hidden
34 />
35 { label }
36 </span>
37 );
38 }
39
40 function ActivateButton( { onClick, disabled, isBusy } ) {
41 return (
42 <button
43 type="button"
44 className="button advads-button-neutral is-small"
45 onClick={ onClick }
46 disabled={ disabled }
47 aria-busy={ isBusy }
48 >
49 { __( 'Activate', 'advanced-ads' ) }
50 </button>
51 );
52 }
53
54 function ActiveWithDeactivate( { onDeactivate, isBusy, isDeactivating } ) {
55 return (
56 <div className="inline-flex flex-wrap items-center gap-3">
57 <span className="inline-flex items-center gap-2 text-sm text-green-700">
58 <Check
59 className="size-4 shrink-0"
60 strokeWidth={ 2 }
61 aria-hidden
62 />
63 { __( 'Active', 'advanced-ads' ) }
64 </span>
65 <button
66 type="button"
67 className="button advads-button-secondary is-small"
68 onClick={ onDeactivate }
69 disabled={ isBusy }
70 aria-busy={ isDeactivating }
71 >
72 { __( 'Deactivate', 'advanced-ads' ) }
73 </button>
74 </div>
75 );
76 }
77
78 export function AddonRowActions( {
79 addonId,
80 licenseKey,
81 licenses,
82 downloadUrl = '',
83 isApplied = false,
84 isActivated = false,
85 disabled = false,
86 managedByOtherLicense = false,
87 addonInstallStates = {},
88 noticesContext,
89 isInstalling = false,
90 installFailed = false,
91 installFailedMessage = '',
92 onInstallStart,
93 onInstallEnd,
94 } ) {
95 const [ isWorking, setIsWorking ] = useState( false );
96 const [ isDeactivating, setIsDeactivating ] = useState( false );
97 const { createErrorNotice, removeNotice } = useDispatch( noticesStore );
98 const licensesFromStore = useSelect(
99 ( select ) => select( STORE_NAME ).getLicenses(),
100 []
101 );
102 const licenseList =
103 licensesFromStore.length > 0 ? licensesFromStore : licenses;
104
105 const rowStatus = getAddonRowStatus(
106 addonId,
107 addonInstallStates,
108 isApplied
109 );
110 const { installed } = getAddonInstallState( addonId, addonInstallStates );
111 const isActiveUnderAllAccess = rowStatus === 'installed' && isActivated;
112 const isBusy = isInstalling || isWorking || isDeactivating;
113 const installActionsDisabled = disabled;
114 const takeOverFromOtherLicense =
115 managedByOtherLicense && ! isApplied && installed;
116
117 function showAddonErrorNotice( message ) {
118 const noticeId = `advanced-ads/addon-error-${ addonId }`;
119
120 removeNotice( noticeId, noticesContext );
121 publishLicenseWarningNotice( createErrorNotice, {
122 id: noticeId,
123 context: noticesContext,
124 message,
125 } );
126 }
127
128 async function handleActivateUnderAllAccess() {
129 if ( isBusy || ! licenseKey || ! addonId ) {
130 return;
131 }
132
133 setIsWorking( true );
134 try {
135 await activateAddonFromLicense( licenseKey, addonId, licenseList );
136 } catch ( err ) {
137 showAddonErrorNotice(
138 extractApiErrorMessage( err ) ||
139 __( 'Activation failed.', 'advanced-ads' )
140 );
141 } finally {
142 setIsWorking( false );
143 }
144 }
145
146 async function handleDownloadAndInstall() {
147 if ( isBusy || installActionsDisabled || ! licenseKey || ! addonId ) {
148 return;
149 }
150
151 onInstallStart?.( addonId );
152 setIsWorking( true );
153
154 try {
155 await activateAddonFromLicense( licenseKey, addonId, licenseList );
156 onInstallEnd?.( addonId, false );
157 } catch ( err ) {
158 const message =
159 extractApiErrorMessage( err ) ||
160 __( 'Installation failed.', 'advanced-ads' );
161 showAddonErrorNotice( message );
162 onInstallEnd?.( addonId, true, message );
163 } finally {
164 setIsWorking( false );
165 }
166 }
167
168 async function handleDeactivate() {
169 if ( isBusy || ! addonId ) {
170 return;
171 }
172
173 setIsDeactivating( true );
174
175 try {
176 await deactivateAddonFromLicense( addonId, licenseList );
177 } catch ( err ) {
178 showAddonErrorNotice(
179 extractApiErrorMessage( err ) ||
180 __( 'Deactivation failed.', 'advanced-ads' )
181 );
182 } finally {
183 setIsDeactivating( false );
184 }
185 }
186
187 function handleManualInstall() {
188 const packageUrl = String( downloadUrl ?? '' ).trim();
189 const guideUrl = getManualInstallGuideUrl( addonId );
190
191 if ( packageUrl ) {
192 window.open( packageUrl, '_blank', 'noopener,noreferrer' );
193 }
194
195 window.open( guideUrl, '_blank', 'noopener,noreferrer' );
196 }
197
198 if ( isDeactivating ) {
199 return <BusyStatus label={ __( 'Deactivating…', 'advanced-ads' ) } />;
200 }
201
202 if ( isActiveUnderAllAccess ) {
203 return (
204 <ActiveWithDeactivate
205 onDeactivate={ handleDeactivate }
206 isBusy={ isBusy }
207 isDeactivating={ isDeactivating }
208 />
209 );
210 }
211
212 if ( isInstalling || isWorking ) {
213 return (
214 <BusyStatus
215 label={
216 isWorking && takeOverFromOtherLicense
217 ? __( 'Activating…', 'advanced-ads' )
218 : __( 'Installing…', 'advanced-ads' )
219 }
220 />
221 );
222 }
223
224 if ( takeOverFromOtherLicense ) {
225 return (
226 <div className="inline-flex flex-wrap items-center gap-3">
227 <ActivateButton
228 onClick={ handleActivateUnderAllAccess }
229 disabled={ installActionsDisabled || isBusy }
230 isBusy={ isWorking }
231 />
232 </div>
233 );
234 }
235
236 if ( rowStatus === 'running' && isActivated ) {
237 return (
238 <ActiveWithDeactivate
239 onDeactivate={ handleDeactivate }
240 isBusy={ isBusy }
241 isDeactivating={ isDeactivating }
242 />
243 );
244 }
245
246 if ( rowStatus === 'ready' ) {
247 return (
248 <ActivateButton
249 onClick={ handleActivateUnderAllAccess }
250 disabled={ installActionsDisabled || isBusy }
251 isBusy={ isWorking }
252 />
253 );
254 }
255
256 return (
257 <div className="inline-flex flex-wrap items-center gap-3">
258 { installFailed ? (
259 <span className="inline-flex items-center gap-2 text-sm text-red-700">
260 <AlertCircle
261 className="size-4 shrink-0"
262 strokeWidth={ 2 }
263 aria-hidden
264 />
265 { installFailedMessage ||
266 __( 'Installation failed', 'advanced-ads' ) }
267 </span>
268 ) : null }
269 <button
270 type="button"
271 className="button advads-button-neutral is-small whitespace-nowrap"
272 onClick={ handleDownloadAndInstall }
273 disabled={ installActionsDisabled || isBusy }
274 aria-busy={ isBusy }
275 >
276 { __( 'Download and install', 'advanced-ads' ) }
277 </button>
278 { installFailed ? (
279 <button
280 type="button"
281 className="button advads-button-secondary is-small"
282 onClick={ handleManualInstall }
283 disabled={ installActionsDisabled || isBusy }
284 >
285 { __( 'Manual install', 'advanced-ads' ) }
286 </button>
287 ) : null }
288 </div>
289 );
290 }
291