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 / Agent / workflows / content / components / UpdatePostConfirm.jsx

UpdatePostConfirm.jsx in Extendify 3.1.0, at src/Agent/workflows/content/components/UpdatePostConfirm.jsx

111 lines 3.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useCallback, useEffect, useRef } from '@wordpress/element';
2 import { __ } from '@wordpress/i18n';
3
4 export const UpdatePostConfirm = ({ inputs, onConfirm, onCancel, onRetry }) => {
5 const undoTextReplacements = useCallback(() => {
6 const replacements = inputs.replacements || [];
7 const reversed = replacements.map(({ original, updated }) => ({
8 original: updated,
9 updated: original,
10 }));
11 updateAllTextNodesAndAttributes(reversed);
12 }, [inputs]);
13
14 const confirmed = useRef(false);
15 useEffect(() => {
16 return () => {
17 if (!confirmed.current) undoTextReplacements();
18 };
19 }, []);
20
21 const handleConfirm = () => {
22 confirmed.current = true;
23 onConfirm({ data: inputs });
24 };
25
26 const handleRetry = useCallback(() => {
27 undoTextReplacements();
28 onRetry();
29 }, [undoTextReplacements, onRetry]);
30
31 useEffect(() => {
32 updateAllTextNodesAndAttributes(inputs.replacements);
33 }, [inputs.replacements]);
34
35 return (
36 <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">
37 <div className="rounded-lg border-b border-gray-300 bg-white">
38 <div className="p-3">
39 <p className="m-0 p-0 text-sm text-gray-900">
40 {__(
41 'The agent has made the changes in the browser. Please review and confirm.',
42 'extendify-local',
43 )}
44 </p>
45 </div>
46 </div>
47 <div className="flex flex-wrap justify-start gap-2 p-3">
48 <button
49 type="button"
50 className="flex-1 rounded-sm border border-gray-500 bg-white p-2 text-sm text-gray-900"
51 onClick={onCancel}
52 >
53 {__('Cancel', 'extendify-local')}
54 </button>
55 <button
56 type="button"
57 className="flex-1 rounded-sm border border-gray-500 bg-white p-2 text-sm text-gray-900"
58 onClick={handleRetry}
59 >
60 {__('Try Again', 'extendify-local')}
61 </button>
62 <button
63 type="button"
64 className="flex-1 rounded-sm border border-design-main bg-design-main p-2 text-sm text-white"
65 onClick={handleConfirm}
66 >
67 {__('Save', 'extendify-local')}
68 </button>
69 </div>
70 </div>
71 );
72 };
73
74 const updateAllTextNodesAndAttributes = (replacements) => {
75 const chat = document.getElementById('extendify-agent-chat');
76 const isInChat = (node) => chat?.contains(node);
77 // Update all text nodes
78 const walker = document.createTreeWalker(
79 document.body,
80 NodeFilter.SHOW_TEXT,
81 null,
82 false,
83 );
84 let node = walker.nextNode();
85 while (node) {
86 const current = node;
87 node = walker.nextNode();
88 // Skip nodes that are inside the chat
89 if (isInChat(current.parentNode)) continue;
90
91 for (const { original, updated } of replacements ?? []) {
92 const value = current.nodeValue ?? '';
93 if (!value.includes(original)) continue;
94 current.nodeValue = value.split(original).join(updated);
95 }
96 }
97
98 // Update attributes
99 ['alt', 'title', 'aria-label', 'href', 'data-id'].forEach((attr) => {
100 document.querySelectorAll(`[${attr}]`).forEach((el) => {
101 // Skip elements that are inside the chat
102 if (isInChat(el)) return;
103 for (const { original, updated } of replacements ?? []) {
104 const val = el.getAttribute(attr);
105 if (!val?.includes(original)) continue;
106 el.setAttribute(attr, val.split(original).join(updated));
107 }
108 });
109 });
110 };
111