PluginProbe
Extendify / trunk
Extendify vtrunk
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Shared / components / ProductAccountActivation / ProductAccountActivation.jsx

ProductAccountActivation.jsx in Extendify trunk, at src/Shared/components/ProductAccountActivation/ProductAccountActivation.jsx

152 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
2 import { prewarmRecaptcha } from '@shared/api/pluginsActivation';
3 import { useEffect, useState } from '@wordpress/element';
4 import { isEmail } from '@wordpress/url';
5 import { accountContext } from './accountContext';
6 import { createAccount } from './createAccount';
7 import { partitionPlugins } from './partitionPlugins';
8 import { SetupComplete } from './SetupComplete';
9 import { SetupPlugins } from './SetupPlugins';
10 import {
11 ACCOUNT_STATUS,
12 ACTIVATION_STATUS,
13 usePluginsActivation,
14 } from './usePluginsActivation';
15
16 export const ProductAccountActivation = () => {
17 const [isOpen, setIsOpen] = useState(true);
18 const [submitted, setSubmitted] = useState(null);
19 const { offered, ineligible } = partitionPlugins(
20 window.extSharedData?.showProductActivation,
21 );
22 const [plugins, setPlugins] = useState(offered);
23
24 const [email, setEmail] = useState(window.extSharedData?.userEmail ?? '');
25 const [marketingConsent, setMarketingConsent] = useState(false);
26 const [termsAgreed, setTermsAgreed] = useState(false);
27 const { scriptData, activatePlugins } = usePluginsActivation(
28 plugins,
29 ineligible,
30 );
31
32 useEffect(() => {
33 const style = document.createElement('style');
34 style.textContent = '.grecaptcha-badge { visibility: hidden; }';
35 document.head.appendChild(style);
36 }, []);
37
38 useEffect(() => {
39 // Site keys come from PHP, so the prewarm needs no SWR wait.
40 for (const plugin of offered) {
41 const siteKey = plugin.scriptData?.recaptchaSiteKey;
42 if (siteKey) prewarmRecaptcha(siteKey).catch(() => {});
43 }
44 }, []);
45
46 const handleClose = () => {
47 activatePlugins({
48 status: ACTIVATION_STATUS.skipped,
49 });
50 setIsOpen(false);
51 };
52
53 const trackStatus = (slug, request) => {
54 const record = (status) =>
55 setSubmitted((current) =>
56 current.map((plugin) =>
57 plugin.slug === slug ? { ...plugin, status } : plugin,
58 ),
59 );
60
61 request.then(
62 () => record(ACCOUNT_STATUS.success),
63 () => record(ACCOUNT_STATUS.error),
64 );
65
66 return request;
67 };
68
69 const handleCreateAccounts = async () => {
70 if (!isEmail(email)) return;
71
72 const selectedPlugins = plugins.filter((plugin) => plugin.selected);
73
74 setSubmitted(
75 selectedPlugins.map((plugin) => ({
76 ...plugin,
77 status: ACCOUNT_STATUS.pending,
78 })),
79 );
80
81 const settling = Promise.allSettled(
82 selectedPlugins.map((plugin) =>
83 trackStatus(
84 plugin.slug,
85 createAccount(plugin, {
86 email,
87 marketingConsent,
88 termsAgreed,
89 scriptData: { ...scriptData?.[plugin.slug], ...plugin.scriptData },
90 }),
91 ),
92 ),
93 );
94
95 // A record stuck on pending is a user who left before the answer.
96 await activatePlugins({
97 status: ACTIVATION_STATUS.completed,
98 context: accountContext(selectedPlugins),
99 });
100
101 const results = await settling;
102
103 await activatePlugins({
104 status: ACTIVATION_STATUS.completed,
105 context: accountContext(selectedPlugins, results),
106 });
107 };
108
109 return (
110 plugins.length > 0 && (
111 <Dialog open={isOpen} onClose={() => {}} className="extendify-shared">
112 {/* Utilities on the scope-class element itself never match the prefixed CSS. */}
113 <div className="relative z-high">
114 <DialogBackdrop
115 transition
116 className="fixed inset-0 bg-black/30 transition-opacity data-closed:opacity-0"
117 />
118
119 <div className="z-10 fixed top-0 left-0 right-0 bottom-(--extendify-notification-bar-height,0px) flex items-center justify-center p-4 [body:has(#extendify-agent-chat)_&]:ml-96 [body:has(#extendify-agent-chat)_&]:w-[calc(100%-24rem)]">
120 <DialogPanel
121 transition
122 className="relative w-full max-w-208 max-h-full overflow-hidden flex flex-col bg-white rounded-lg shadow-xl transition-all data-closed:opacity-0 data-closed:scale-95"
123 >
124 <div className="overflow-y-auto">
125 {submitted ? (
126 <SetupComplete
127 plugins={submitted}
128 handleClose={() => setIsOpen(false)}
129 />
130 ) : (
131 <SetupPlugins
132 plugins={plugins}
133 setPlugins={setPlugins}
134 handleCreateAccounts={handleCreateAccounts}
135 email={email}
136 setEmail={setEmail}
137 handleClose={handleClose}
138 marketingConsent={marketingConsent}
139 setMarketingConsent={setMarketingConsent}
140 termsAgreed={termsAgreed}
141 setTermsAgreed={setTermsAgreed}
142 />
143 )}
144 </div>
145 </DialogPanel>
146 </div>
147 </div>
148 </Dialog>
149 )
150 );
151 };
152