diff --git a/web/public/locales/en/components/dialog.json b/web/public/locales/en/components/dialog.json index f23e18e9a..d325b3f13 100644 --- a/web/public/locales/en/components/dialog.json +++ b/web/public/locales/en/components/dialog.json @@ -54,6 +54,7 @@ "newCaseNamePlaceholder": "New case name", "newCaseDescriptionPlaceholder": "Case description", "label": "Case", + "nonAdminHelp": "A new case will be created for these exports.", "placeholder": "Select a case" }, "select": "Select", @@ -79,6 +80,21 @@ "exportButton_one": "Export 1 Camera", "exportButton_other": "Export {{count}} Cameras" }, + "multi": { + "title_one": "Export 1 review", + "title_other": "Export {{count}} reviews", + "description": "Export each selected review. All exports will be grouped under a single case.", + "caseNamePlaceholder": "Review export - {{date}}", + "exportButton_one": "Export 1 review", + "exportButton_other": "Export {{count}} reviews", + "exportingButton": "Exporting...", + "toast": { + "started_one": "Started 1 export. Opening the case now.", + "started_other": "Started {{count}} exports. Opening the case now.", + "partial": "Started {{successful}} of {{total}} exports. Failed: {{failedItems}}", + "failed": "Failed to start {{total}} exports. Failed: {{failedItems}}" + } + }, "toast": { "success": "Successfully started export. View the file in the exports page.", "queued": "Export queued. View progress in the exports page.", diff --git a/web/src/components/card/ReviewCard.tsx b/web/src/components/card/ReviewCard.tsx index 0ae8d376d..6fb72a6fa 100644 --- a/web/src/components/card/ReviewCard.tsx +++ b/web/src/components/card/ReviewCard.tsx @@ -81,7 +81,7 @@ export default function ReviewCard({ axios .post( - `export/${event.camera}/start/${event.start_time + REVIEW_PADDING}/end/${endTime}`, + `export/${event.camera}/start/${event.start_time - REVIEW_PADDING}/end/${endTime}`, { playback: "realtime" }, ) .then((response) => { diff --git a/web/src/components/filter/ReviewActionGroup.tsx b/web/src/components/filter/ReviewActionGroup.tsx index 31c5a56f4..389d12104 100644 --- a/web/src/components/filter/ReviewActionGroup.tsx +++ b/web/src/components/filter/ReviewActionGroup.tsx @@ -6,6 +6,7 @@ import { isDesktop } from "react-device-detect"; import { FaCompactDisc } from "react-icons/fa"; import { HiTrash } from "react-icons/hi"; import { ReviewSegment } from "@/types/review"; +import { MAX_BATCH_EXPORT_ITEMS } from "@/types/export"; import { AlertDialog, AlertDialogAction, @@ -20,6 +21,7 @@ import useKeyboardListener from "@/hooks/use-keyboard-listener"; import { Trans, useTranslation } from "react-i18next"; import { toast } from "sonner"; import { useIsAdmin } from "@/hooks/use-is-admin"; +import MultiExportDialog from "../overlay/MultiExportDialog"; type ReviewActionGroupProps = { selectedReviews: ReviewSegment[]; @@ -164,6 +166,29 @@ export default function ReviewActionGroup({ )} )} + {selectedReviews.length >= 2 && + selectedReviews.length <= MAX_BATCH_EXPORT_ITEMS && ( + { + onClearSelected(); + pullLatestData(); + }} + > + + + )}