diff --git a/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx b/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx index 3b5bd4d46..dd1228066 100644 --- a/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx +++ b/src/admin/components/ResourceTabs/PolygonReviewTab/index.tsx @@ -31,7 +31,6 @@ import { IconNames } from "@/components/extensive/Icon/Icon"; import ModalAdd from "@/components/extensive/Modal/ModalAdd"; import ModalConfirm from "@/components/extensive/Modal/ModalConfirm"; import { ModalId } from "@/components/extensive/Modal/ModalConst"; -import { useLoading } from "@/context/loaderAdmin.provider"; import { useMapAreaContext } from "@/context/mapArea.provider"; import { useModalContext } from "@/context/modal.provider"; import { useMonitoredDataContext } from "@/context/monitoredData.provider"; @@ -152,7 +151,6 @@ const PolygonReviewTab: FC = props => { const [saveFlags, setSaveFlags] = useState(false); const [polygonFromMap, setPolygonFromMap] = useState({ isOpen: false, uuid: "" }); const [errorMessage, setErrorMessage] = useState(null); - const { showLoader, hideLoader } = useLoading(); const { setSelectedPolygonsInCheckbox, setPolygonCriteriaMap, @@ -314,8 +312,7 @@ const PolygonReviewTab: FC = props => { }, [shouldRefetchValidation]); const uploadFiles = async () => { const uploadPromises = []; - showLoader(); - + closeModal(ModalId.ADD_POLYGON); for (const file of files) { const fileToUpload = file.rawFile as File; const site_uuid = record.uuid; @@ -350,10 +347,8 @@ const PolygonReviewTab: FC = props => { } refetch(); refetchSiteBbox(); - closeModal(ModalId.ADD_POLYGON); setPolygonLoaded(false); setSubmitPolygonLoaded(false); - hideLoader(); } catch (error) { let errorMessage; @@ -379,7 +374,6 @@ const PolygonReviewTab: FC = props => { errorMessage = t("An unknown error occurred"); } openNotification("error", t("Error uploading file"), errorMessage || t("An unknown error occurred")); - hideLoader(); } }; diff --git a/src/admin/modules/sites/components/SiteShow.tsx b/src/admin/modules/sites/components/SiteShow.tsx index fb0bef090..7662bf547 100644 --- a/src/admin/modules/sites/components/SiteShow.tsx +++ b/src/admin/modules/sites/components/SiteShow.tsx @@ -1,8 +1,7 @@ -import { FC, useState } from "react"; +import { FC } from "react"; import { Show, TabbedShowLayout } from "react-admin"; import ShowActions from "@/admin/components/Actions/ShowActions"; -import DelayedJobsProgressAlert from "@/admin/components/Alerts/DelayedJobsProgressAlert"; import AuditLogTab from "@/admin/components/ResourceTabs/AuditLogTab/AuditLogTab"; import { AuditLogButtonStates } from "@/admin/components/ResourceTabs/AuditLogTab/constants/enum"; import ChangeRequestsTab from "@/admin/components/ResourceTabs/ChangeRequestsTab/ChangeRequestsTab"; @@ -16,9 +15,6 @@ import { RecordFrameworkProvider } from "@/context/framework.provider"; import { MapAreaProvider } from "@/context/mapArea.provider"; const SiteShow: FC = () => { - const [isLoadingDelayedJob, setIsLoadingDelayedJob] = useState(false); - const [alertTitle, setAlertTitle] = useState(""); - return ( record?.name} />} @@ -30,13 +26,7 @@ const SiteShow: FC = () => { - + @@ -46,11 +36,6 @@ const SiteShow: FC = () => { - ); }; diff --git a/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx b/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx index 3c824d575..4d919fe53 100644 --- a/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx +++ b/src/components/elements/Map-mapbox/MapControls/CheckPolygonControl.tsx @@ -200,6 +200,7 @@ const CheckPolygonControl = (props: CheckSitePolygonProps) => { const runFixPolygonOverlaps = () => { if (siteUuid) { + closeModal(ModalId.FIX_POLYGONS); setIsLoadingDelayedJob?.(true); setAlertTitle?.("Fix Polygons"); clipPolygons({ pathParams: { uuid: siteUuid } }); diff --git a/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx b/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx index d57df4bc9..b267f6622 100644 --- a/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx +++ b/src/components/elements/Map-mapbox/MapControls/ProcessBulkPolygonsControl.tsx @@ -111,6 +111,7 @@ const ProcessBulkPolygonsControl = ({ className: "px-8 py-3", variant: "primary", onClick: () => { + closeModal(ModalId.FIX_POLYGONS); setIsLoadingDelayedJob?.(true); setAlertTitle?.("Fix Polygons"); fixPolygons( @@ -124,7 +125,7 @@ const ProcessBulkPolygonsControl = ({ { onSuccess: response => { const processedNames = response?.processed?.map(item => item.poly_name).join(", "); - closeModal(ModalId.FIX_POLYGONS); + setIsLoadingDelayedJob?.(false); ApiSlice.addTotalContent(0); ApiSlice.addProgressContent(0); diff --git a/src/components/elements/Notification/FloatNotification.tsx b/src/components/elements/Notification/FloatNotification.tsx index 45e6e2af9..19bc31633 100644 --- a/src/components/elements/Notification/FloatNotification.tsx +++ b/src/components/elements/Notification/FloatNotification.tsx @@ -1,8 +1,13 @@ +import { LinearProgress } from "@mui/material"; +import { useT } from "@transifex/react"; import classNames from "classnames"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { When } from "react-if"; import Icon, { IconNames } from "@/components/extensive/Icon/Icon"; +import { triggerBulkUpdate, useDelayedJobs } from "@/connections/DelayedJob"; +import { DelayedJobData, DelayedJobDto } from "@/generated/v3/jobService/jobServiceSchemas"; +import { getErrorMessageFromPayload } from "@/utils/errors"; import LinearProgressBar from "../ProgressBar/LinearProgressBar/LinearProgressBar"; import Text from "../Text/Text"; @@ -17,8 +22,50 @@ export interface FloatNotificationProps { data: FloatNotificationDataProps[]; } -const FloatNotification = ({ data }: FloatNotificationProps) => { +const FloatNotification = () => { + const t = useT(); const [openModalNotification, setOpenModalNotification] = useState(false); + const [isLoaded, { delayedJobs }] = useDelayedJobs(); + const [notAcknowledgedJobs, setNotAcknowledgedJobs] = useState([]); + const clearJobs = () => { + if (delayedJobs === undefined) return; + const newJobsData: DelayedJobData[] = delayedJobs + .filter((job: DelayedJobDto) => job.status !== "pending") + .map((job: DelayedJobDto) => { + return { + uuid: job.uuid, + type: "delayedJobs", + attributes: { + isAcknowledged: true + } + }; + }); + triggerBulkUpdate(newJobsData); + }; + useEffect(() => { + if (delayedJobs === undefined) return; + const notAcknowledgedJobs = delayedJobs.filter((job: DelayedJobDto) => !job.isAcknowledged); + setNotAcknowledgedJobs(notAcknowledgedJobs); + }, [delayedJobs]); + useEffect(() => { + if (!notAcknowledgedJobs.length) { + setOpenModalNotification(false); + } + }, [notAcknowledgedJobs]); + const listOfPolygonsFixed = (data: Record | null) => { + if (data?.updated_polygons) { + const updatedPolygonNames = data.updated_polygons + ?.map((p: any) => p.poly_name) + .filter(Boolean) + .join(", "); + if (updatedPolygonNames) { + return "Success! The following polygons have been fixed: " + updatedPolygonNames; + } else { + return "No polygons were fixed"; + } + } + return null; + }; return (
@@ -31,43 +78,88 @@ const FloatNotification = ({ data }: FloatNotificationProps) => { )} > - Notifications + {t("Notifications")}
- Actions Taken + {t("Actions Taken")} - - Clear completed + + {t("Clear completed")}
- {data.map((item, index) => ( -
-
-
- - {item.label} - -
- - Site: {item.site} - -
- - - {item.value} + {isLoaded && + notAcknowledgedJobs && + notAcknowledgedJobs.map((item, index) => ( +
+
+
+ + {item.name} + +
+ + Site: {item.entityName} +
+ {item.status === "failed" ? ( + + {item.payload ? t(getErrorMessageFromPayload(item.payload)) : t("Failed to complete")} + + ) : ( +
+ {item.name === "Polygon Upload" && + (item.processedContent === null || item.totalContent === null) && + item.status === "pending" ? ( +
+ +
+ ) : ( + + )} + + {item.name === "Polygon Upload" + ? item.status === "succeeded" + ? t("Done!") + : "" + : item.status === "succeeded" + ? t("Done!") + : `${Math.round(((item.processedContent ?? 0) / (item.totalContent ?? 1)) * 100)}%`} + +
+ )} + + {item.status === "succeeded" && ( + + {listOfPolygonsFixed(item.payload)} + + )} +
-
- ))} + ))}
- 0}> + 0}>
- {data.length} + {notAcknowledgedJobs?.length}