diff --git a/frontend/src/App.css b/frontend/src/App.css index a34a3fe5..541fad93 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -1,5 +1,5 @@ body { - font-family: 'Manrope'; + font-family: Manrope; } #root { @@ -53,7 +53,7 @@ body { #log-container>* { color: white; font-size: 13px; - font-family: "Monospace", sans-serif !important; + font-family: Monospace, sans-serif !important; font-weight: 400; font-style: normal !important; } @@ -273,7 +273,7 @@ th { .required{ border: 2px solid red !important; - font-family: 'manrope'; + font-family: Manrope; } .expanded { @@ -599,6 +599,9 @@ padding-left: 0; background: transparent; border: none; cursor: pointer; + height: 100%; + width: 50px; + background-color: transparent !important; } .password-feedback-container { margin-top: 8px; @@ -616,10 +619,6 @@ padding-left: 0; height: 20px; } -.show-password-btn{ - background-color: transparent !important; -} - .search-bar-wrapper{ flex-grow: 1; margin-right: 1rem; @@ -755,7 +754,7 @@ padding-left: 0; /*Form Label*/ .form-control{ - font-family: 'Manrope'; + font-family: Manrope; font-size: 1rem; font-weight: bold; } diff --git a/frontend/src/components/MatchReviewers/MatchReviewersForm.jsx b/frontend/src/components/MatchReviewers/MatchReviewersForm.jsx index ee19b719..651d389d 100644 --- a/frontend/src/components/MatchReviewers/MatchReviewersForm.jsx +++ b/frontend/src/components/MatchReviewers/MatchReviewersForm.jsx @@ -56,14 +56,23 @@ const MatchReviewersForm = ({ updateInputFieldsErrors("selectedModal", "Required"); noError = false; } + if (!inputFields.numberOfTopReviewers) { updateInputFieldsErrors("numberOfTopReviewers", "Required"); noError = false; + } else if (isNaN(inputFields.numberOfTopReviewers) || inputFields.numberOfTopReviewers < 0) { + updateInputFieldsErrors("numberOfTopReviewers", "Must be a valid positive number."); + noError = false; } + if (!inputFields.closeCollaboratorTimeFrame) { updateInputFieldsErrors("closeCollaboratorTimeFrame", "Required"); noError = false; + } else if (isNaN(inputFields.closeCollaboratorTimeFrame) || inputFields.closeCollaboratorTimeFrame < 0) { + updateInputFieldsErrors("closeCollaboratorTimeFrame", "Must be a valid positive number."); + noError = false; } + if (textAreaError) { setTextAreaError("Required"); noError = false; diff --git a/frontend/src/components/util/Logs.jsx b/frontend/src/components/util/Logs.jsx index 95065a1d..c2f56265 100644 --- a/frontend/src/components/util/Logs.jsx +++ b/frontend/src/components/util/Logs.jsx @@ -18,7 +18,6 @@ const Logs = ({ preventClick, setShowLogs, mode, - usePrompt, currentCycle, currentTaskId, }) => { @@ -41,8 +40,6 @@ const Logs = ({ ? "Process Successful!" : "Process Failed!"; - usePrompt("A process is running. Do you really want to leave?", progressPercentage < 100); - return ( <> { - if (!when) { - return; - } - - const push = navigator.push; - - navigator.push = (...args) => { - const result = confirmExit(); - if (result !== false) { - push(...args); + if (progressPercentage <= 0 || progressPercentage >= 100) return; + + const handlePopState = async(event) => { + event.preventDefault(); + const stay = window.confirm(message); + if (stay) { + // If user chooses to stay, do nothing + window.history.pushState(null, "", location.pathname); // This keeps them on the current page + } else { + // If they choose to leave, you can handle any cleanup here + await terminateAllProcesses(); + navigate(-1); } }; - + + window.addEventListener("popstate", handlePopState); + return () => { - navigator.push = push; + window.removeEventListener("popstate", handlePopState); }; - }, [navigator, confirmExit, when]); - } - - function usePrompt(message, when = true) { + }, [progressPercentage, message]); + useEffect(() => { - const handleBeforeUnload = async (event) => { - event.preventDefault(); - event.returnValue = message; - await terminateAllProcesses(); - return ""; - }; - if (when) { + if (progressPercentage > 0 && progressPercentage < 100) { + let isLeaving = false; + + const handleBeforeUnload = (event) => { + event.preventDefault(); + event.returnValue = message; + }; + + const handleUnload = async () => { + if (isLeaving) { + await terminateAllProcesses(); + } + }; + + const handleConfirmLeave = () => { + isLeaving = true; + }; + window.addEventListener("beforeunload", handleBeforeUnload); + window.addEventListener("unload", handleUnload); + window.addEventListener("beforeunload", handleConfirmLeave); + + return () => { + window.removeEventListener("beforeunload", handleBeforeUnload); + window.removeEventListener("unload", handleUnload); + window.removeEventListener("beforeunload", handleConfirmLeave); + }; } - return () => { - window.removeEventListener("beforeunload", handleBeforeUnload); - }; - }, [message, when]); - - const confirmExit = useCallback(() => { - const confirm = window.confirm(message); - if (confirm) { - terminateAllProcesses(); - } - return confirm; - }, [message]); - useConfirmExit(confirmExit, when); + }, [progressPercentage, message]); } + useCustomBlocker(progressPercentage, + "A process is running. Do you really want to leave?" + ); + return ( <> {renderFormComponent({ @@ -238,7 +253,6 @@ const PageComponent = ({ ) : showLogs ? ( { {label} -
+
{ }${disabled ? "disabled" : ""}`} disabled={disabled} autoFocus + style={{ paddingRight: '40px' }} // Adjust padding to make space for the button /> {error && ( { type="button" className="show-password-btn" disabled={disabled} - style={{ right: error ? "45px" : "" }} + style={{ + position: 'absolute', + right: '1px', + }} >