PluginProbe
Extendify / 3.1.0
Extendify v3.1.0
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 / AutoLaunch / components / CreatingSite.jsx

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

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