PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
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 / Agent / workflows / block-selector / components / UpdateBlockConfirm.jsx

UpdateBlockConfirm.jsx in Extendify 3.0.4, at src/Agent/workflows/block-selector/components/UpdateBlockConfirm.jsx

151 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { patchVariantClasses } from '@agent/lib/variant-classes';
2 import { useWorkflowStore } from '@agent/state/workflows';
3 import apiFetch from '@wordpress/api-fetch';
4 import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
5 import { __ } from '@wordpress/i18n';
6
7 const dynamicClasses = ['is-style-ext-preset', 'is-style-outline'];
8
9 export const UpdateBlockConfirm = ({
10 inputs,
11 onConfirm,
12 onCancel,
13 onRetry,
14 }) => {
15 const { block } = useWorkflowStore();
16 const [loading, setLoading] = useState(true);
17 const detachedEl = useRef(null);
18
19 const undoBlockChange = useCallback(() => {
20 const el = document.querySelector('[data-extendify-temp-replacement]');
21 if (detachedEl.current) {
22 el?.parentNode?.insertBefore(detachedEl.current, el);
23 detachedEl.current = null;
24 }
25 if (el) el.remove();
26 }, []);
27
28 const confirmed = useRef(false);
29 useEffect(() => {
30 return () => {
31 if (!confirmed.current) undoBlockChange();
32 };
33 }, []);
34
35 const handleConfirm = async () => {
36 confirmed.current = true;
37 await onConfirm({ data: inputs, shouldRefreshPage: true });
38 };
39
40 const handleRetry = useCallback(() => {
41 undoBlockChange();
42 onRetry();
43 }, [undoBlockChange, onRetry]);
44
45 useEffect(() => {
46 apiFetch({
47 path: '/extendify/v1/agent/get-block-html',
48 method: 'POST',
49 data: { blockCode: inputs.newContent },
50 }).then(({ content }) => {
51 // Remove the highlighter
52 window.dispatchEvent(new Event('extendify-agent:remove-block-highlight'));
53 // hide the block
54 const el = document.querySelector(
55 `[data-extendify-agent-block-id="${block.id}"]`,
56 );
57 // TODO: work out a way to propagate an error here
58 if (!el && !detachedEl.current) return onCancel();
59 if (detachedEl.current) return; // already done
60 detachedEl.current = el;
61
62 const patched = patchVariantClasses(
63 content,
64 el.cloneNode(true),
65 dynamicClasses,
66 );
67
68 const template = document.createElement('template');
69 template.innerHTML = patched || '<div style="display:none"></div>';
70 const newEl = template.content.firstElementChild;
71 if (!newEl) return onCancel();
72 const wpBlockAttributeClasses =
73 /^has-([\w-]+-)?(background-color|color|font-size|gradient-background)$|^has-background$|^has-text-color$/;
74 const newElClasses = new Set(newEl.classList);
75 el.classList.forEach((className) => {
76 if (newElClasses.has(className)) return;
77 if (wpBlockAttributeClasses.test(className)) return;
78 newEl.classList.add(className);
79 });
80 newEl.setAttribute('data-extendify-temp-replacement', true);
81 // Strip animation classes so the preview is visible immediately.
82 // The ext-animate--on class sets opacity:0 as initial state, but
83 // the animation JS won't re-run on replaced DOM elements.
84 for (const node of [
85 newEl,
86 ...newEl.querySelectorAll('.ext-animate--on'),
87 ]) {
88 node.classList.remove('ext-animate--on');
89 }
90 el.parentNode.insertBefore(newEl, el.nextSibling);
91 el.parentNode?.removeChild(el);
92 setLoading(false);
93 });
94 }, [block, inputs, onCancel]);
95
96 if (loading)
97 return (
98 <Wrapper>
99 <Content>{__('Loading...', 'extendify-local')}</Content>
100 </Wrapper>
101 );
102
103 return (
104 <Wrapper>
105 <Content>
106 <p className="m-0 p-0 text-sm text-gray-900">
107 {__(
108 'The agent has made the changes in the browser. Please review and confirm.',
109 'extendify-local',
110 )}
111 </p>
112 </Content>
113 <div className="flex flex-wrap justify-start gap-2 p-3">
114 <button
115 type="button"
116 className="flex-1 rounded-sm border border-gray-500 bg-white p-2 text-sm text-gray-900"
117 onClick={onCancel}
118 >
119 {__('Cancel', 'extendify-local')}
120 </button>
121 <button
122 type="button"
123 className="flex-1 rounded-sm border border-gray-500 bg-white p-2 text-sm text-gray-900"
124 onClick={handleRetry}
125 >
126 {__('Try Again', 'extendify-local')}
127 </button>
128 <button
129 type="button"
130 className="flex-1 rounded-sm border border-design-main bg-design-main p-2 text-sm text-white"
131 onClick={handleConfirm}
132 >
133 {__('Save', 'extendify-local')}
134 </button>
135 </div>
136 </Wrapper>
137 );
138 };
139
140 const Wrapper = ({ children }) => (
141 <div className="mb-4 ml-10 mr-2 flex flex-col rounded-lg border border-gray-300 bg-gray-50 rtl:ml-2 rtl:mr-10">
142 {children}
143 </div>
144 );
145
146 const Content = ({ children }) => (
147 <div className="rounded-lg border-b border-gray-300 bg-white">
148 <div className="p-3">{children}</div>
149 </div>
150 );
151