PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.7
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.7
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / src / admin / pages / Settings / SettingsOptions.js

SettingsOptions.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.7, at src/admin/pages/Settings/SettingsOptions.js

416 lines 12.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useState, useEffect } from "@wordpress/element";
2 import { __ } from "@wordpress/i18n";
3 import Toggle from "react-toggle";
4 import Select from "react-select";
5 import { SelectField } from "../../../components";
6 import { saveSettingOptions, renderInfoText, SaveAndReset } from "./functions";
7
8 const jsToPhpBool = (val) => {
9 return val ? "1" : "0";
10 };
11
12 const phpToJsBool = {
13 0: false,
14 1: true,
15 };
16
17 export const SiteAvailability = ({ settingsOptions, setSettingsOptions }) => {
18 const [initialValues, setInitialValues] = useState({
19 siteMode: settingsOptions?.pcp_site_mode || "live",
20 selectPage: settingsOptions?.pcp_select_page || "",
21 });
22 const [siteMode, setSiteMode] = useState(initialValues.siteMode);
23 const [selectPage, setSelectPage] = useState(initialValues.selectPage);
24 const [pages, setPages] = useState([]);
25 const [isSaving, setIsSaving] = useState(false);
26
27 const isChanged = initialValues.siteMode !== siteMode || initialValues.selectPage !== selectPage;
28
29 const saveSiteAvailabilityOptions = (actionType = "save") => {
30 const updatedSettings = {
31 pcp_site_mode: siteMode,
32 pcp_select_page: selectPage,
33 };
34 setIsSaving(true);
35
36 saveSettingOptions(updatedSettings, actionType, setSettingsOptions).then(() => {
37 setInitialValues({
38 siteMode,
39 selectPage,
40 });
41 setIsSaving(false);
42 });
43 };
44
45 return (
46 <div className="sp-pcp-settings-advanced-controls">
47 <div className="sp-pcp-settings-option">
48 <div className="sp-pcp-option-label-wrapper">
49 <span className="sp-pcp-component-title">
50 {__("Site Mode", "post-carousel")}
51 </span>
52 <span className="sp-pcp-option-help-text">
53 {renderInfoText("siteMode")}
54 </span>
55 </div>
56 <div className="sp-pcp-blocks-settings-select-field">
57 <SelectField
58 value={siteMode}
59 onChange={(val) => setSiteMode(val)}
60 items={[
61 { label: __("Live", "post-carousel"), value: "live" },
62 {
63 label: __("Coming Soon (Pro)", "post-carousel"),
64 value: "coming_soon",
65 disabled: true,
66 },
67 {
68 label: __("Maintenance (Pro)", "post-carousel"),
69 value: "maintenance",
70 disabled: true,
71 },
72 ]}
73 />
74 </div>
75 </div>
76 {siteMode !== "live" && (
77 <div className="sp-pcp-settings-option">
78 <div className="sp-pcp-option-label-wrapper">
79 <span className="sp-pcp-component-title">{__("Select Page", "post-carousel")}</span>
80 </div>
81 <div className="sp-pcp-blocks-settings-select-field">
82 <SelectField
83 value={selectPage}
84 onChange={(val) => setSelectPage(val)}
85 items={pages}
86 defaultOption={true}
87 />
88 </div>
89 </div>
90 )}
91 <SaveAndReset
92 onSave={() => saveSiteAvailabilityOptions("save")}
93 isChanged={isChanged}
94 isSaving={isSaving}
95 />
96 </div>
97 );
98 };
99
100 export const Advanced = ({ settingsOptions, setSettingsOptions }) => {
101 const [initialValues, setInitialValues] = useState({
102 cleanDataOnDelete: phpToJsBool[settingsOptions?.pcp_delete_all_data] || false,
103 });
104 const [isSaving, setIsSaving] = useState(false);
105
106 const [cleanDataOnDelete, setCleanDataOnDelete] = useState(initialValues.cleanDataOnDelete);
107
108 const isChanged = initialValues.cleanDataOnDelete !== cleanDataOnDelete;
109
110 const saveAdvancedControls = (actionType = "save") => {
111 const newCleanOnDelete = cleanDataOnDelete;
112
113 const updatedSettings = {
114 pcp_delete_all_data: jsToPhpBool(newCleanOnDelete),
115 };
116 setIsSaving(true);
117
118 saveSettingOptions(updatedSettings, actionType, setSettingsOptions).then(() => {
119 setInitialValues({
120 cleanDataOnDelete: newCleanOnDelete,
121 });
122 setIsSaving(false);
123 });
124 };
125
126 return (
127 <div className="sp-pcp-settings-advanced-controls">
128 <div className="sp-pcp-settings-option">
129 <div className="sp-pcp-option-label-wrapper">
130 <span className="sp-pcp-component-title">
131 {__("Clean-up Data on Deletion", "post-carousel")}
132 </span>
133 <span className="sp-pcp-option-help-text">
134 {renderInfoText("cleanOnDeletion")}
135 </span>
136 </div>
137 <div className="sp-pcp-blocks-settings-toggle-btn">
138 <Toggle
139 checked={cleanDataOnDelete}
140 icons={false}
141 onChange={() => setCleanDataOnDelete(!cleanDataOnDelete)}
142 />
143 </div>
144 </div>
145
146 <SaveAndReset onSave={() => saveAdvancedControls("save")} isChanged={isChanged} isSaving={isSaving} />
147 </div>
148 );
149 };
150
151 export const Tools = ({ setPage }) => {
152 const [exportType, setExportType] = useState("all-shows");
153 const [selectedFile, setSelectedFile] = useState(null);
154 const [fileName, setFileName] = useState(__("No File Choosen", "post-carousel"));
155 const [shortcodeList, setShortcodeList] = useState([]);
156 const [selectedShortcodes, setSelectedShortcodes] = useState([]);
157 const [isImporting, setIsImporting] = useState(false);
158 const [isDragging, setIsDragging] = useState(false);
159
160 // Fetch shortcode list using AJAX
161 useEffect(() => {
162 const formData = new FormData();
163 formData.append("action", "pcp_get_shortcode_list_for_export");
164
165 fetch(ajaxurl, {
166 method: "POST",
167 body: formData,
168 })
169 .then((response) => response.json())
170 .then((data) => {
171 if (data.success && Array.isArray(data.data)) {
172 const list = data.data.map((post) => ({
173 label: post.title || `#${post.id}`,
174 value: post.id,
175 }));
176 setShortcodeList(list);
177 } else {
178 setShortcodeList([]);
179 }
180 })
181 .catch((error) => {
182 console.error("Error fetching shortcode list:", error);
183 setShortcodeList([]);
184 });
185 }, []);
186
187 const handleFileChange = (e) => {
188 const file = e.target.files[0];
189 if (file) {
190 setSelectedFile(file);
191 setFileName(file.name);
192 }
193 };
194
195 const handleDragEnter = (e) => {
196 e.preventDefault();
197 e.stopPropagation();
198 setIsDragging(true);
199 };
200
201 const handleDragLeave = (e) => {
202 e.preventDefault();
203 e.stopPropagation();
204 // Only set dragging to false if leaving the actual drop zone
205 if (e.target === e.currentTarget) {
206 setIsDragging(false);
207 }
208 };
209
210 const handleDragOver = (e) => {
211 e.preventDefault();
212 e.stopPropagation();
213 };
214
215 const handleDrop = (e) => {
216 e.preventDefault();
217 e.stopPropagation();
218 setIsDragging(false);
219
220 const files = e.dataTransfer.files;
221 if (files && files.length > 0) {
222 const file = files[0];
223 const acceptedExtensions = ['.json', '.csv'];
224 const fileExtension = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();
225
226 if (acceptedExtensions.includes(fileExtension)) {
227 setSelectedFile(file);
228 setFileName(file.name);
229 } else {
230 alert(__("Please select a valid JSON or CSV file.", "post-carousel"));
231 }
232 }
233 };
234
235 const handleExport = () => {
236 // Export functionality
237 const exportValue = exportType === "all-shows" ? "all_shortcodes" : "selected_shortcodes";
238 const selectedShortcode = exportValue === "selected_shortcodes" ? selectedShortcodes.join(",") : "all_shortcodes";
239
240 if (
241 exportValue === "all_shortcodes" ||
242 (exportValue === "selected_shortcodes" && selectedShortcodes.length > 0)
243 ) {
244 const formData = new FormData();
245 formData.append("action", "pcp_export_shortcodes");
246 formData.append("pcp_ids", selectedShortcode);
247
248 fetch(ajaxurl, {
249 method: "POST",
250 body: formData,
251 })
252 .then((response) => response.text())
253 .then((resp) => {
254 if (resp) {
255 // Convert JSON Array to string.
256 let json;
257 try {
258 const parsed = JSON.parse(resp);
259 json = JSON.stringify(parsed);
260 } catch {
261 json = JSON.stringify(resp);
262 }
263
264 // Convert JSON string to BLOB.
265 const blob = new Blob([json], { type: "application/json" });
266 const link = document.createElement("a");
267 const timestamp = Date.now();
268 link.href = window.URL.createObjectURL(blob);
269 link.download = "smart-post-show-" + timestamp + ".json";
270 link.click();
271 }
272 });
273 }
274 };
275
276 const handleImport = () => {
277 // Import functionality
278 if (selectedFile) {
279 setIsImporting(true);
280 const reader = new FileReader();
281 reader.onload = (e) => {
282 const fileContent = e.target.result;
283 const formData = new FormData();
284 formData.append("action", "pcp_import_shortcodes");
285 formData.append("shortcode", fileContent);
286
287 fetch(ajaxurl, {
288 method: "POST",
289 body: formData,
290 })
291 .then((response) => response.json())
292 .then((data) => {
293 setIsImporting(false);
294 if (data.success) {
295 // alert(__("Import successful!", "post-carousel"));
296 setSelectedFile(null);
297 setFileName(__("No File Choosen", "post-carousel"));
298 setPage("savedTemplate");
299 } else {
300 alert(data.data?.message || __("Import failed.", "post-carousel"));
301 }
302 })
303 .catch((error) => {
304 setIsImporting(false);
305 console.error("Import error:", error);
306 alert(__("Import failed.", "post-carousel"));
307 });
308 };
309 reader.readAsText(selectedFile);
310 }
311 };
312
313 return (
314 <div className="sp-pcp-settings-tools-controls">
315 <div className="sp-pcp-settings-tools-section">
316 <div className="sp-pcp-settings-tools-section-header">
317 <h3 className="sp-pcp-settings-tools-section-title">{__("Export", "post-carousel")}</h3>
318 </div>
319 <div className="sp-pcp-settings-tools-section-content">
320 <p className="sp-pcp-settings-tools-subtitle">{__("Choose What to Export", "post-carousel")}</p>
321 <div className="sp-pcp-settings-tools-radio-group">
322 <label className={`sp-pcp-settings-tools-radio ${exportType === "all-shows" ? "active" : ""}`}>
323 <input
324 type="radio"
325 name="export-type"
326 value="all-shows"
327 checked={exportType === "all-shows"}
328 onChange={() => setExportType("all-shows")}
329 />
330 <span className="sp-pcp-settings-tools-radio-label">
331 {__("All Shows (Shortcodes)", "post-carousel")}
332 </span>
333 </label>
334 <label
335 className={`sp-pcp-settings-tools-radio ${exportType === "selected-shows" ? "active" : ""}`}
336 >
337 <input
338 type="radio"
339 name="export-type"
340 value="selected-shows"
341 checked={exportType === "selected-shows"}
342 onChange={() => setExportType("selected-shows")}
343 />
344 <span className="sp-pcp-settings-tools-radio-label">
345 {__("Selected Show(s)", "post-carousel")}
346 </span>
347 </label>
348 </div>
349
350 {exportType === "selected-shows" && (
351 <div className="sp-pcp-settings-tools-multiselect">
352 <Select
353 isMulti
354 value={shortcodeList.filter((item) => selectedShortcodes.includes(item.value))}
355 onChange={(selectedOptions) => {
356 const values = selectedOptions ? selectedOptions.map((opt) => opt.value) : [];
357 setSelectedShortcodes(values);
358 }}
359 options={shortcodeList}
360 placeholder={__("Choose show(s)", "post-carousel")}
361 className="sp-pcp-tools-multi-select"
362 classNamePrefix="sp-pcp-tools"
363 noOptionsMessage={() => __("No shows available", "post-carousel")}
364 />
365 </div>
366 )}
367 <button
368 className="sp-pcp-settings-tools-btn sp-pcp-settings-tools-btn-primary"
369 onClick={handleExport}
370 >
371 {__("Export File", "post-carousel")}
372 </button>
373 </div>
374 </div>
375
376 <div className="sp-pcp-settings-tools-divider"></div>
377
378 <div className="sp-pcp-settings-tools-section">
379 <div className="sp-pcp-settings-tools-section-header">
380 <h3 className="sp-pcp-settings-tools-section-title">{__("Import", "post-carousel")}</h3>
381 </div>
382 <div className="sp-pcp-settings-tools-section-content">
383 <p className="sp-pcp-settings-tools-subtitle">
384 {__("Import JSON File to Upload", "post-carousel")}
385 </p>
386 <div
387 className={`sp-pcp-settings-tools-file-input${isDragging ? ' dragging' : ''}`}
388 onDragEnter={handleDragEnter}
389 onDragLeave={handleDragLeave}
390 onDragOver={handleDragOver}
391 onDrop={handleDrop}
392 >
393 <label className="sp-pcp-settings-tools-file-btn">
394 {__("Choose File", "post-carousel")}
395 <input
396 type="file"
397 accept=".json,.csv"
398 onChange={handleFileChange}
399 style={{ display: "none" }}
400 />
401 </label>
402 <span className="sp-pcp-settings-tools-file-name">{fileName}</span>
403 </div>
404 <button
405 className={`sp-pcp-settings-tools-btn sp-pcp-settings-tools-btn-secondary${selectedFile ? " has-file" : ""}`}
406 onClick={handleImport}
407 disabled={!selectedFile || isImporting}
408 >
409 {isImporting ? __("Importing...", "post-carousel") : __("Import File", "post-carousel")}
410 </button>
411 </div>
412 </div>
413 </div>
414 );
415 };
416