Skip to content

Commit

Permalink
Merge pull request #2277 from abilpraju-aot/FWF-3727
Browse files Browse the repository at this point in the history
updated code for export form
  • Loading branch information
arun-s-aot authored Oct 16, 2024
2 parents 87033ce + 9aa9c52 commit 06aa4ec
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 9 deletions.
3 changes: 2 additions & 1 deletion forms-flow-web/src/apiManager/endpoints/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ const API = {
GET_FILTERS : `${WEB_BASE_URL}/filter`,
GET_BPM_TASK_FILTERS : `${BPM_BASE_URL_EXT}/v1/task-filters`,
VALIDATE_TENANT: `${MT_ADMIN_BASE_URL}/${MT_ADMIN_BASE_URL_VERSION}/tenants/<tenant_id>/validate`,
VALIDATE_FORM_NAME: `${WEB_BASE_URL}/form/validate`
VALIDATE_FORM_NAME: `${WEB_BASE_URL}/form/validate`,
EXPORT_FORM: `${WEB_BASE_URL}/form/<form_id>/export`
};

export default API;
5 changes: 5 additions & 0 deletions forms-flow-web/src/apiManager/services/FormServices.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,8 @@ export const validateFormName = (title, name, id) => {
}
return RequestService.httpGETRequest(url);
};

export const getFormExport = (form_id) => {
const exportFormUrl = replaceUrl(API.EXPORT_FORM, "<form_id>",form_id);
return RequestService.httpGETRequest(exportFormUrl);
};
26 changes: 18 additions & 8 deletions forms-flow-web/src/components/Form/Item/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
getProcessDetails,
getFormProcesses
} from "../../../apiManager/services/processServices";

import { setProcessData } from '../../../actions/processActions.js';

import _isEquial from "lodash/isEqual";
Expand All @@ -42,12 +42,13 @@ import { useParams } from "react-router-dom";

import SettingsModal from "../../CustomComponents/settingsModal";
import FlowEdit from "./FlowEdit.js";
import ExportModal from "../../Modals/ExportModal.js";

// constant values
const DUPLICATE = "DUPLICATE";
// const SAVE_AS_TEMPLATE= "SAVE_AS_TEMPLATE";
// const IMPORT= "IMPORT";
// const EXPORT= "EXPORT";
const EXPORT = "EXPORT";
//const DELETE = "DELETE";

const reducer = (form, { type, value }) => {
Expand Down Expand Up @@ -83,6 +84,7 @@ const Edit = React.memo(() => {
const processListData = useSelector(
(state) => state.process?.formProcessList
);

const formAuthorization = useSelector((state) => state.process.authorizationDetails);
const formData = useSelector((state) => state.form?.form);
const [form, dispatchFormAction] = useReducer(reducer, _cloneDeep(formData));
Expand All @@ -93,7 +95,7 @@ const Edit = React.memo(() => {
const { formId } = useParams();
const [nameError, setNameError] = useState("");

// flow edit
// flow edit
const [isProcessDetailsLoading, setIsProcessDetailsLoading] = useState(false);

//for save form
Expand Down Expand Up @@ -214,7 +216,7 @@ const Edit = React.memo(() => {
}
}, [formId]);





Expand Down Expand Up @@ -394,13 +396,13 @@ const Edit = React.memo(() => {
console.log("handleHistory");
};



const handlePreview = () => {
console.log("handlePreview");
};



const discardChanges = () => {
console.log("discardChanges");
Expand Down Expand Up @@ -524,7 +526,7 @@ const Edit = React.memo(() => {

//get mapper data

//call for new version save
//call for new version save
setShowSaveModal(true);
};

Expand Down Expand Up @@ -566,6 +568,8 @@ const Edit = React.memo(() => {
setFormSubmitted(false);
});
};


return (
<div>
<div>
Expand Down Expand Up @@ -712,7 +716,7 @@ const Edit = React.memo(() => {
</Card>
</div>
<div className={`wraper flow-wraper ${showFlow ? "visible" : ""}`}>
{isProcessDetailsLoading ? <>loading...</> :
{isProcessDetailsLoading ? <>loading...</> :
<FlowEdit />}
</div>
{showFlow && (
Expand Down Expand Up @@ -757,6 +761,12 @@ const Edit = React.memo(() => {
nameValidationOnBlur={validateFormNameOnBlur}
nameError={nameError}
/>

<ExportModal
showExportModal={selectedAction === EXPORT}
onClose={handleCloseSelectedAction}
formId={processListData.id}
/>
<ConfirmModal
show={showSaveModal}
title={<Translation>{(t) => t("Save Your Changes")}</Translation>}
Expand Down
160 changes: 160 additions & 0 deletions forms-flow-web/src/components/Modals/ExportModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React, { useState, useEffect } from "react";
import Modal from "react-bootstrap/Modal";
import { CloseIcon, CustomButton, FailedIcon } from "@formsflow/components";
import ProgressBar from "react-bootstrap/ProgressBar";
import { Translation } from "react-i18next";
import { getFormExport } from "../../apiManager/services/FormServices";

const ExportModal = React.memo(({ showExportModal, onClose, formId }) => {
const [progress, setProgress] = useState(0);
const [exportStatus, setExportStatus] = useState("Export in Progress");
const [isExportComplete, setIsExportComplete] = useState(false);
const [isError, setIsError] = useState(false); // Flag to indicate if an error occurred

const exportForm = () => {
// Ensure the progress is reset before starting the export process
setProgress(0);
setExportStatus("Export in Progress");
setIsExportComplete(false);
setIsError(false); // Reset the error state on retry

getFormExport(formId, {
responseType: "blob", // Ensure the response is treated as binary
onDownloadProgress: (progressEvent) => {
if (progressEvent.lengthComputable) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
setProgress(percentCompleted);
} else {
// Fallback: Manually increment progress if length is not computable
setProgress((prevProgress) => Math.min(prevProgress + 10, 100)); // Increment progress manually
}
},
})
.then((response) => {
const jsonString = JSON.stringify(response.data, null, 2); // Pretty-print JSON
const blob = new Blob([jsonString], { type: "application/json" });
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = downloadUrl;
link.download = "FileName.json";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

// Once the download is complete, mark the progress as 100%
setProgress(100);
setExportStatus("Export Successful");
setIsExportComplete(true);
})
.catch((error) => {
const errorMessage = error.response?.data?.message || "Export Failed";

// Set the progress to 100% even when there is an error
setProgress(100);
setExportStatus(errorMessage);
setIsError(true); // Mark the export as failed
setIsExportComplete(true);
});
};

// Reset the progress when the modal is closed or when the export finishes
useEffect(() => {
if (showExportModal) {
exportForm();
} else {
// Reset progress when modal is closed
setProgress(0);
setIsExportComplete(false);
setIsError(false);
}
}, [showExportModal, formId]);

return (
<Modal
show={showExportModal}
onHide={onClose}
dialogClassName="modal-50w" // This will control the modal width
centered // Center the modal on the screen
aria-labelledby="contained-modal-title-vcenter"
scrollable // Ensures content is scrollable on small screens
>
<Modal.Header>
<Modal.Title>
<b>
<Translation>{(t) => t("Export Form")}</Translation>
</b>
</Modal.Title>
<div className="d-flex align-items-center">
<CloseIcon width="16.5" height="16.5" onClick={onClose} />
</div>
</Modal.Header>
<Modal.Body className="build-modal-body">
<ProgressBar
now={progress}
animated={!isExportComplete && !isError}
variant="primary" // Always primary for the progress bar
/>
<div className="mt-2 text-wrap d-flex align-items-center">
{/* Keep FileName.json black */}
<span className="text-dark">FileName.json&nbsp;</span>
<span className={isError ? "text-danger" : "text-primary"}>
{/* Display the failure message in red or success message in blue */}
{isError ? (
<Translation>
{(t) => (
<>
{t("Export Failed")} <FailedIcon color="red" />
</>
)}
</Translation>
) : (
<Translation>{(t) => t(exportStatus)}</Translation>
)}
</span>
</div>
{isError && (
<div className="text-danger mt-2">
<p>
<Translation>
{(t) =>
t("A system error occurred during export. Please try again.")
}
</Translation>
</p>
</div>
)}
</Modal.Body>
<Modal.Footer className="d-flex justify-content-start flex-wrap">
{isError && ( // Only show buttons if there's an error
<>
<CustomButton
variant="primary"
size="md"
label={<Translation>{(t) => t("Try Again")}</Translation>}
onClick={() => {
setProgress(0); // Reset progress before retrying
exportForm();
}}
className="mb-2"
dataTestid="try-again"
ariaLabel="Try Again"
/>
<CustomButton
variant="secondary"
size="md"
label={<Translation>{(t) => t("Cancel")}</Translation>}
onClick={onClose}
className="mb-2"
dataTestid="cancel"
ariaLabel="Cancel"
/>
</>
)}
</Modal.Footer>
</Modal>
);
});

export default ExportModal;

0 comments on commit 06aa4ec

Please sign in to comment.