import React, { useState, useEffect } from "react"; import apiFetch from "@wordpress/api-fetch"; import { __ } from "@wordpress/i18n"; import { validFieldProps, isObject } from "quickbuilder"; // This component will send form data on submit const ImporterUpload = (props) => { const validProps = validFieldProps(props, [ "is_pro", "visible", "trigger", "disable", "parentIndex", "context", "copyOnClick", "description", "label", "help", "style", ]); const [selectedFile, setSelectedFile] = useState(null); const [isLoading, setIsLoading] = useState(false); const [existingSlugs, setExistingSlugs] = useState([]); const [selectedAction, setSelectedAction] = useState("ignore"); // from withLabel field let { label, label_subtitle, id, name, type, style: prevStyle, is_pro, badge, value, enable_disable_text_active = false, ...rest } = props; // const instanceId = useInstanceId(withLabel); if (id == undefined) { id = name; } const styles = { description: { position: "right", }, ...prevStyle, }; const classNames = (...args) => args.filter(Boolean).join(" "); const styleClasses = classNames({ [`wprf-style-${styles?.type}`]: styles?.type || false, "wprf-label-none": label === undefined || label === "" || label.length === 0, [`wprf-${styles?.label?.position || "inline"}-label`]: (styles?.label?.position ?? true) && label != undefined, }); if (type === "hidden") { return ; } const componentClasses = classNames( "wprf-control-wrapper", `wprf-type-${type}`, styleClasses, props?.classes, { [`wprf-name-${name}`]: name, }, ); const handleRadioChange = (e) => { setSelectedAction(e.target.value); }; const handleFileChange = (e) => { if (!e.target.files.length) { return; } const file = e.target.files[0]; if (file?.size == 0) { props.context.alerts.toast( "error", __('File can\'t be empty.', "betterdocs"), ); return; } else if ( file?.type !== "application/json" && file?.type !== "text/json" && file?.type !== "application/xml" && // MIME type for XML file?.type !== "text/xml" && file?.type !== "text/csv" && file?.type !== "application/csv" && file?.type !== "application/vnd.ms-excel" // MIME types for CSV ) { props.context.alerts.toast( "error", __('Invalid file type.', "betterdocs"), ); return; } setSelectedFile(file); // Check file type and call respective functions if (file.type === "application/xml" || file.type === "text/xml") { let reader = new FileReader(); reader.onload = function (e) { // e.target.result contains the file data const fileData = e.target.result; // Parse the XML string const parser = new DOMParser(); const xmlDoc = parser.parseFromString(fileData, "text/xml"); // Define the WordPress namespace const wpNamespace = "http://wordpress.org/export/1.2/"; // Use XPath to extract wp:post_name values let data = {}; const postSlugs = []; const nodes = xmlDoc.evaluate( "//wp:post_name", xmlDoc, (prefix) => { return prefix === "wp" ? wpNamespace : null; }, XPathResult.ANY_TYPE, null, ); let node = nodes.iterateNext(); while (node) { postSlugs.push(node.textContent); node = nodes.iterateNext(); } if (postSlugs) { data["posts"] = postSlugs; } apiFetch({ path: "/betterdocs/v1/parse-xml", method: "POST", data: data, }) .then((response) => { if (response.status === "success" && response.data) { setExistingSlugs(Object.values(response.data)); } }) .catch((error) => { console.log(error); }); }; // Read the file as text or binary, depending on your needs reader.readAsText(file); } else if ( file.type === "text/csv" || file.type === "application/csv" || file.type === "application/vnd.ms-excel" ) { handleCSVFile(file); } }; const handleCSVFile = (file) => { const formData = new FormData(); formData.append("file", file); apiFetch({ path: "/betterdocs/v1/parse-csv", method: "POST", body: formData, }) .then((response) => { if (response.status === "success" && response.data) { setExistingSlugs(Object.values(response.data)); } }) .catch((error) => { console.log(error); }); }; const handleUpload = () => { setIsLoading(true); const formData = new FormData(); formData.append("file", selectedFile); // Add other form data to the FormData object { existingSlugs.length > 0 && formData.append("existing_slug", existingSlugs.join(",")); } const selectedAction = document.querySelector( 'input[name="action"]:checked', ); if (selectedAction) { formData.append("action", selectedAction.value); } apiFetch({ path: props.ajax.api, method: "POST", body: formData, }) .then((response) => { setIsLoading(false); if (response.status === "failed") { throw new Error(); } if (response.status === "success") { setSelectedFile(null); if (!props.ajax?.hideSwal) { const type = props.ajax?.swal?.icon || "success"; const message = props.ajax?.swal?.text || "Complete"; props.context.alerts.toast(type, message, { autoClose: props.ajax?.swal?.autoClose, }); } if (props.ajax?.reload) { setTimeout(() => window.location.reload(), 1000); } } }) .catch((error) => { setIsLoading(true); if (!props.ajax?.hideSwal) { props.context.alerts.toast( "error", error?.message || __("Something went wrong.", "betterdocs"), ); } }); }; const removeFile = () => { setSelectedFile(null); props.onChange({ target: { type: "importerupload", name: props.name, value: null, }, }); }; return ( <>
{label && } {label_subtitle && (

)}
{selectedFile === null ? ( ) : ( selectedFile.name && ( <> {selectedFile.name.length > 20 ? `${selectedFile.name.substr( 0, 9, )}...${selectedFile.name.substr( selectedFile.name.length - 7, )}` : selectedFile.name} {existingSlugs.length > 0 && ( <>
{props?.text ?.exists_notice && (

{ props?.text ?.exists_notice }

)}
)} ) )}
{selectedFile && (
)} ); }; export default ImporterUpload;