PluginProbe
Extendify / 3.1.5
Extendify v3.1.5
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 0.7.0 All 126 releases
extendify / src / AutoLaunch / components / CreatingSite.jsx

CreatingSite.jsx in Extendify 3.1.5, at src/AutoLaunch/components/CreatingSite.jsx

162 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useCreateSite } from '@auto-launch/hooks/useCreateSite';
2 import { useRateLimitedCursor } from '@auto-launch/hooks/useRateLimitedCursor';
3 import { loaderSiteCreation } from '@auto-launch/icons';
4 import {
5 clearPersistedLaunchData,
6 useLaunchDataStore,
7 } from '@auto-launch/state/launch-data';
8 import { useEffect, useRef, useState } from '@wordpress/element';
9 import { __ } from '@wordpress/i18n';
10 import { Icon, info } from '@wordpress/icons';
11 import { AnimatePresence, motion } from 'framer-motion';
12
13 const { adminUrl, homeUrl } = window.extSharedData;
14
15 export const CreatingSite = ({ height }) => {
16 const { done } = useCreateSite();
17 const pos = useRef(0);
18 const [currentMessage, setCurrentMessage] = useState(null);
19 const [loadAdmin, setLoadAdmin] = useState(false);
20 const {
21 statusMessages,
22 errorMessage,
23 setErrorMessage,
24 errorCount,
25 needToStall,
26 resetErrorCount,
27 setPulse,
28 } = useLaunchDataStore();
29
30 useRateLimitedCursor(
31 () => {
32 if (errorMessage) return false;
33 if (pos.current >= statusMessages.length) return false;
34
35 const remaining = statusMessages.length - pos.current;
36 const MAX_BACKLOG = 3;
37
38 // Skip ahead silently if backed up
39 if (remaining > MAX_BACKLOG && pos.current > 0) {
40 pos.current = statusMessages.length - MAX_BACKLOG;
41 }
42
43 setCurrentMessage(statusMessages[pos.current]);
44 pos.current += 1;
45
46 return pos.current < statusMessages.length;
47 },
48 // Variable timer to feel more natural, 2.5-3.25s
49 Math.floor(2500 + Math.random() * 750),
50 [statusMessages.length],
51 );
52
53 useEffect(() => {
54 if (!errorMessage) return;
55 const timeout = setTimeout(() => {
56 // Clear after 5 seconds
57 setErrorMessage(null);
58 }, 5000);
59 return () => clearTimeout(timeout);
60 }, [errorMessage, setErrorMessage]);
61
62 useEffect(() => {
63 setPulse(!done);
64 }, [done]);
65
66 useEffect(() => {
67 if (!done) return;
68 setLoadAdmin(true);
69 const timeout = setTimeout(() => {
70 clearPersistedLaunchData();
71 window.location.replace(`${homeUrl}?extendify-launch-success=1`);
72 }, 3000);
73 return () => clearTimeout(timeout);
74 }, [done]);
75
76 useEffect(() => {
77 if (!needToStall()) return;
78 const timer = setTimeout(() => {
79 resetErrorCount();
80 }, 10000); // reset after 10 seconds
81 return () => clearTimeout(timer);
82 }, [needToStall, errorCount, resetErrorCount]);
83
84 if (needToStall()) {
85 return (
86 <div
87 className="w-full rounded-3xl border border-gray-300 bg-[#F0F0F0CC]/80 backdrop-blur-[80px] p-6 flex items-center gap-2"
88 style={{
89 boxShadow: '0px 4px 30px 0px #0000001A',
90 }}
91 >
92 <div className="flex gap-2">
93 <div className="w-6 shrink-0 pt-0.5">
94 <Icon icon={info} size={24} />
95 </div>
96 <div className="flex flex-col gap-2">
97 <span className="text-lg font-semibold leading-7 text-gray-900">
98 {__('We are experiencing some delays', 'extendify-local')}
99 </span>
100 <span className="text-base font-normal leading-6 text-gray-900">
101 {__('Pausing for a few seconds', 'extendify-local')}
102 </span>
103 </div>
104 </div>
105 </div>
106 );
107 }
108
109 return (
110 <div
111 className="w-full rounded-3xl border border-gray-300 bg-gray-100/80 backdrop-blur-2xl shadow-md flex flex-col items-center justify-center gap-3 relative"
112 style={{
113 height: height || 'auto',
114 }}
115 >
116 <div className="text-design-main">{loaderSiteCreation}</div>
117 <div className="h-5 overflow-hidden">
118 <AnimatePresence mode="wait">
119 {currentMessage ? (
120 <motion.p
121 key={currentMessage}
122 initial={{ opacity: 0, y: 8 }}
123 animate={{ opacity: 1, y: 0 }}
124 exit={{ opacity: 0 }}
125 transition={{ duration: 0.25 }}
126 className="m-0 text-sm font-medium leading-5 text-center status-animation"
127 >
128 {currentMessage}
129 </motion.p>
130 ) : null}
131 </AnimatePresence>
132 </div>
133 {errorMessage ? (
134 <div
135 className="absolute left-0 w-full rounded-3xl border border-gray-300 bg-[#F0F0F0CC] backdrop-blur-[80px] px-6 py-3 flex items-center gap-2"
136 style={{
137 top: 'calc(100% + 24px)',
138 boxShadow: '0px 4px 30px 0px #0000001A',
139 }}
140 >
141 <Icon icon={info} size={24} />
142 <span className="text-sm font-medium leading-5 text-gray-900">
143 {errorMessage}
144 </span>
145 </div>
146 ) : null}
147 {loadAdmin ? <AdminLoader /> : null}
148 </div>
149 );
150 };
151
152 // iframe that loads the admin in the background to make sure
153 // all php functions that require admin context work properly.
154 const AdminLoader = () => (
155 <iframe
156 title="Admin Loader"
157 src={adminUrl}
158 style={{ display: 'none' }}
159 sandbox="allow-same-origin allow-scripts allow-forms"
160 />
161 );
162