PluginProbe ʕ •ᴥ•ʔ
Hostinger Reach – AI-Powered Email Marketing for WordPress / 1.7.0
Hostinger Reach – AI-Powered Email Marketing for WordPress v1.7.0
1.7.1 1.7.0 1.6.0 1.5.9 1.5.8 1.5.7 1.5.6 1.5.5 1.5.4 1.5.3 1.5.2 1.5.1 1.5.0 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 trunk 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6
hostinger-reach / frontend / blocks / subscription-block / src / edit.js
hostinger-reach / frontend / blocks / subscription-block / src Last commit date
Components 9 months ago autoloader.js 1 year ago edit.js 6 months ago ic-arrow-up-right-square.svg 11 months ago index.js 6 months ago reach-logo.svg 11 months ago styles.scss 1 month ago view.js 1 month ago
edit.js
278 lines
1 import {useState, useEffect} from "react";
2 import apiFetch from '@wordpress/api-fetch';
3 import {useSelect, select} from '@wordpress/data';
4
5 import ServerSideRender from "@wordpress/server-side-render";
6 import {useBlockProps, InspectorControls} from "@wordpress/block-editor";
7 import {
8 PanelBody,
9 SelectControl,
10 TextControl,
11 ToggleControl,
12 CheckboxControl, Flex, FlexItem, Button,
13 } from "@wordpress/components";
14 import {__} from '@wordpress/i18n';
15 import Connect from "./Components/Connect";
16 import Dialog from "./Components/Dialog";
17
18 const Edit = ({attributes, setAttributes, clientId}) => {
19 const {isPostPublished, postPermalink} = useSelect((select) => ({
20 isPostPublished: select('core/editor').isCurrentPostPublished()
21 }));
22 const [newTagName, setNewTagName] = useState('');
23 const blockProps = useBlockProps();
24 const nonce = wp.data.select('core/editor').getEditorSettings().nonce || '';
25 const [isConnected, setIsConnected] = useState(true);
26 const [showAddNewTag, setShowAddNewTag] = useState(false);
27 const [isLoading, setIsLoading] = useState(false);
28 const [tags, setTags] = useState([]);
29 const [showDialog, setShowDialog] = useState(false);
30 const [lastStatus, setLastStatus] = useState(null);
31
32 const layoutOptions = [
33 {label: __('Default', 'hostinger-reach'), value: 'default'},
34 {label: __('Inline', 'hostinger-reach'), value: 'inline'}
35 ];
36
37 useEffect(() => {
38 if (isPostPublished && lastStatus !== null && lastStatus !== 'publish') {
39 setShowDialog(true);
40 }
41 }, [isPostPublished, lastStatus]);
42
43
44 useEffect(() => {
45 setLastPostStatus();
46 fetchTags();
47 checkConnection();
48 }, []);
49
50
51 useEffect(() => {
52 if (attributes.formId) return;
53 setAttributes({formId: clientId});
54 }, [setAttributes]);
55
56 const fetchTags = async () => {
57 await getTags();
58 };
59
60
61 const checkConnection = async () => {
62 try {
63 const response = await apiFetch({
64 path: '/hostinger-reach/v1/overview',
65 method: 'GET',
66 headers: {
67 'X-WP-Nonce': nonce,
68 },
69 parse: false,
70 });
71
72 if (response.ok) {
73 setIsConnected(true);
74 } else {
75 setIsConnected(false);
76 }
77
78 } catch (err) {
79 setIsConnected(false);
80 }
81 }
82
83 const setLastPostStatus = () => {
84 const lastKnownStatus = select('core/editor').getEditedPostAttribute('status');
85 setLastStatus(lastKnownStatus);
86 }
87
88 const getTags = async () => {
89 try {
90 const response = await apiFetch({
91 path: '/hostinger-reach/v1/tags',
92 method: 'GET',
93 headers: {
94 'X-WP-Nonce': nonce,
95 },
96 parse: false,
97 });
98
99 if (response.ok) {
100 const responseData = await response.json();
101 const tagNames = responseData.data.map(tag => tag.value);
102 setTags(tagNames);
103 }
104 } catch (err) {
105 console.error(err);
106 }
107 }
108
109 const createTag = async ( tag ) => {
110 try {
111 setIsLoading(true);
112 const response = await apiFetch({
113 path: '/hostinger-reach/v1/tags',
114 method: 'POST',
115 headers: {
116 'X-WP-Nonce': nonce,
117 },
118 data: {
119 names: [tag]
120 },
121 });
122
123 if (response && response.data) {
124 const tagNames = response.data.map(tag => tag.value);
125 setTags([...tagNames, ...tags]);
126 }
127 } catch ( err ) {
128 console.error(err);
129 } finally {
130 setIsLoading(false);
131 }
132 }
133
134 const isTagSelected = (tagName) => {
135 const selectedTags = attributes.tags || [];
136 return selectedTags.includes(tagName);
137 }
138
139 const handleTagToggle = (tagName) => {
140 const selectedTags = attributes.tags || [];
141 let newTags;
142 if (isTagSelected(tagName)) {
143 newTags = selectedTags.filter(tag => tag !== tagName);
144 } else {
145 newTags = [...selectedTags, tagName];
146 }
147
148 setAttributes({tags: newTags});
149 };
150
151 const addTag = async () => {
152 const newTag = newTagName.trim();
153
154 if (!newTag) {
155 return;
156 }
157
158 const tagExists = tags.some(tag => tag === newTag);
159
160 if (!tagExists) {
161 await createTag( newTag );
162 }
163
164 if (!isTagSelected(newTag)) {
165 handleTagToggle(newTag);
166 }
167
168 setNewTagName('');
169 }
170
171 const handleKeyPress = (event) => {
172 if (event.key === 'Enter') {
173 event.preventDefault();
174 addTag();
175 }
176 };
177
178 const toggleAddNewTag = () => {
179 setShowAddNewTag( ! showAddNewTag );
180 }
181
182 return <div {...blockProps}>
183 <InspectorControls key="hostinger-reach-block-controls">
184 <PanelBody title={__("Settings", "hostinger-reach")}>
185 {!isConnected && <Connect/>}
186 <TextControl
187 disabled
188 label={__('Form ID', 'hostinger-reach')}
189 value={attributes.formId}
190 help={__('Unique identifier for this form', 'hostinger-reach')}
191 />
192 <div>
193 <strong>{__('Tags', 'hostinger-reach')}</strong>
194 {tags.length > 0 && (
195 <div className="hostinger-reach-block-tags">
196 {tags.map((tag) => {
197 const selectedTags = attributes.tags || [];
198 return (
199 <CheckboxControl
200 key={tag}
201 label={tag}
202 checked={selectedTags.includes(tag)}
203 onChange={() => handleTagToggle(tag)}
204 />
205 );
206 })}
207 </div>
208 )}
209 </div>
210 <Button
211 className="hostinger-reach-block-toggler"
212 variant="link"
213 onClick={toggleAddNewTag}
214 >
215 {__('Add New Tag', 'hostinger-reach')}
216 </Button>
217 {showAddNewTag && <Flex className="hostinger-reach-block-newtag" direction="column" align="flex-start" gap={1}>
218 <FlexItem style={{flex: 1}}>
219 <TextControl
220 label={__('New Tag Name', 'hostinger-reach')}
221 value={newTagName}
222 onChange={(value) => {
223 setNewTagName(value);
224 }}
225 onKeyDown={handleKeyPress}
226 help={__('Enter tag name and press Enter or click Add Tag', 'hostinger-reach')}
227 />
228 </FlexItem>
229 <FlexItem>
230 <Button
231 variant="secondary"
232 onClick={addTag}
233 disabled={!newTagName.trim() || isLoading}
234 >
235 {__('Add Tag', 'hostinger-reach')}
236 </Button>
237 </FlexItem>
238 </Flex> }
239 <ToggleControl
240 label={__("Show Name Field?", "hostinger-reach")}
241 key="hostinger-reach-block-show-name-field"
242 checked={attributes.showName}
243 onChange={(value) =>
244 setAttributes({showName: value})
245 }
246 />
247 <ToggleControl
248 label={__("Show Surname Field?", "hostinger-reach")}
249 key="hostinger-reach-block-show-surname-field"
250 checked={attributes.showSurname}
251 onChange={(value) =>
252 setAttributes({showSurname: value})
253 }
254 />
255 </PanelBody>
256 <PanelBody title={__('Layout Settings', 'hostinger-reach')}>
257 <SelectControl
258 label={__('Layout', 'hostinger-reach')}
259 value={attributes.layout}
260 options={layoutOptions}
261 onChange={(value) => setAttributes({layout: value})}
262 />
263 </PanelBody>
264
265 </InspectorControls>
266 {!isConnected && <Connect/>}
267 <ServerSideRender
268 key="hostinger-reach-server-side-renderer"
269 block="hostinger-reach/subscription"
270 attributes={attributes}
271 />
272 {showDialog && <Dialog onClose={() => setShowDialog(false)}/>}
273 </div>
274
275 }
276
277 export default Edit;
278