forked from Github/frigate
Remove paging (#10310)
* Remove paging and use reviewed as an internal filter * Fix new reviews not going away
This commit is contained in:
@@ -19,9 +19,6 @@ import axios from "axios";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import useSWR from "swr";
|
||||
import useSWRInfinite from "swr/infinite";
|
||||
|
||||
const API_LIMIT = 100;
|
||||
|
||||
export default function Events() {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
@@ -41,7 +38,6 @@ export default function Events() {
|
||||
useApiFilter<ReviewFilter>();
|
||||
|
||||
const onUpdateFilter = useCallback((newFilter: ReviewFilter) => {
|
||||
setSize(1);
|
||||
setReviewFilter(newFilter);
|
||||
// we don't want this updating
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -69,53 +65,25 @@ export default function Events() {
|
||||
return axios.get(path, { params }).then((res) => res.data);
|
||||
}, []);
|
||||
|
||||
const getKey = useCallback(
|
||||
(index: number, prevData: ReviewSegment[]) => {
|
||||
if (index > 0) {
|
||||
const lastDate = prevData[prevData.length - 1].start_time;
|
||||
reviewSearchParams;
|
||||
const pagedParams = {
|
||||
cameras: reviewSearchParams["cameras"],
|
||||
labels: reviewSearchParams["labels"],
|
||||
reviewed: reviewSearchParams["showReviewed"],
|
||||
before: lastDate,
|
||||
after: reviewSearchParams["after"] || last24Hours.after,
|
||||
limit: API_LIMIT,
|
||||
};
|
||||
return ["review", pagedParams];
|
||||
}
|
||||
const getKey = useCallback(() => {
|
||||
const params = {
|
||||
cameras: reviewSearchParams["cameras"],
|
||||
labels: reviewSearchParams["labels"],
|
||||
reviewed: 1,
|
||||
before: reviewSearchParams["before"] || last24Hours.before,
|
||||
after: reviewSearchParams["after"] || last24Hours.after,
|
||||
};
|
||||
return ["review", params];
|
||||
}, [reviewSearchParams, last24Hours]);
|
||||
|
||||
const params = {
|
||||
cameras: reviewSearchParams["cameras"],
|
||||
labels: reviewSearchParams["labels"],
|
||||
reviewed: reviewSearchParams["showReviewed"],
|
||||
limit: API_LIMIT,
|
||||
before: reviewSearchParams["before"] || last24Hours.before,
|
||||
after: reviewSearchParams["after"] || last24Hours.after,
|
||||
};
|
||||
return ["review", params];
|
||||
const { data: reviews, mutate: updateSegments } = useSWR<ReviewSegment[]>(
|
||||
getKey,
|
||||
reviewSegmentFetcher,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
[reviewSearchParams, last24Hours],
|
||||
);
|
||||
|
||||
const {
|
||||
data: reviewPages,
|
||||
mutate: updateSegments,
|
||||
size,
|
||||
setSize,
|
||||
isValidating,
|
||||
} = useSWRInfinite<ReviewSegment[]>(getKey, reviewSegmentFetcher, {
|
||||
revalidateOnFocus: false,
|
||||
persistSize: true,
|
||||
});
|
||||
|
||||
const isDone = useMemo(
|
||||
() => (reviewPages?.at(-1)?.length ?? 0) < API_LIMIT,
|
||||
[reviewPages],
|
||||
);
|
||||
|
||||
const onLoadNextPage = useCallback(() => setSize(size + 1), [size, setSize]);
|
||||
|
||||
// review summary
|
||||
|
||||
const { data: reviewSummary, mutate: updateSummary } = useSWR<ReviewSummary>([
|
||||
@@ -136,24 +104,20 @@ export default function Events() {
|
||||
// preview videos
|
||||
|
||||
const previewTimes = useMemo(() => {
|
||||
if (
|
||||
!reviewPages ||
|
||||
reviewPages.length == 0 ||
|
||||
reviewPages.at(-1)?.length == 0
|
||||
) {
|
||||
if (!reviews || reviews.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const startDate = new Date();
|
||||
startDate.setMinutes(0, 0, 0);
|
||||
|
||||
const endDate = new Date(reviewPages.at(-1)?.at(-1)?.end_time || 0);
|
||||
const endDate = new Date(reviews.at(-1)?.end_time || 0);
|
||||
endDate.setHours(0, 0, 0, 0);
|
||||
return {
|
||||
start: startDate.getTime() / 1000,
|
||||
end: endDate.getTime() / 1000,
|
||||
};
|
||||
}, [reviewPages]);
|
||||
}, [reviews]);
|
||||
const { data: allPreviews } = useSWR<Preview[]>(
|
||||
previewTimes
|
||||
? `preview/all/start/${previewTimes.start}/end/${previewTimes.end}`
|
||||
@@ -169,28 +133,21 @@ export default function Events() {
|
||||
|
||||
if (resp.status == 200) {
|
||||
updateSegments(
|
||||
(data: ReviewSegment[][] | undefined) => {
|
||||
(data: ReviewSegment[] | undefined) => {
|
||||
if (!data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
const newData: ReviewSegment[][] = [];
|
||||
const reviewIndex = data.findIndex((item) => item.id == review.id);
|
||||
if (reviewIndex == -1) {
|
||||
return data;
|
||||
}
|
||||
|
||||
data.forEach((page) => {
|
||||
const reviewIndex = page.findIndex(
|
||||
(item) => item.id == review.id,
|
||||
);
|
||||
|
||||
if (reviewIndex == -1) {
|
||||
newData.push([...page]);
|
||||
} else {
|
||||
newData.push([
|
||||
...page.slice(0, reviewIndex),
|
||||
{ ...page[reviewIndex], has_been_reviewed: true },
|
||||
...page.slice(reviewIndex + 1),
|
||||
]);
|
||||
}
|
||||
});
|
||||
const newData = [
|
||||
...data.slice(0, reviewIndex),
|
||||
{ ...data[reviewIndex], has_been_reviewed: true },
|
||||
...data.slice(reviewIndex + 1),
|
||||
];
|
||||
|
||||
return newData;
|
||||
},
|
||||
@@ -252,7 +209,7 @@ export default function Events() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!reviewPages) {
|
||||
if (!reviews) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -262,8 +219,6 @@ export default function Events() {
|
||||
|
||||
const allCameras = reviewFilter?.cameras ?? Object.keys(config.cameras);
|
||||
|
||||
const allReviews = reviewPages.flat();
|
||||
|
||||
if (selectedReviewId.startsWith("motion")) {
|
||||
const motionData = selectedReviewId.split(",");
|
||||
// format is motion,camera,start_time
|
||||
@@ -272,15 +227,13 @@ export default function Events() {
|
||||
severity: "significant_motion" as ReviewSeverity,
|
||||
start_time: parseFloat(motionData[2]),
|
||||
allCameras: allCameras,
|
||||
cameraSegments: allReviews.filter((seg) =>
|
||||
cameraSegments: reviews.filter((seg) =>
|
||||
allCameras.includes(seg.camera),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
const selectedReview = allReviews.find(
|
||||
(item) => item.id == selectedReviewId,
|
||||
);
|
||||
const selectedReview = reviews.find((item) => item.id == selectedReviewId);
|
||||
|
||||
if (!selectedReview) {
|
||||
return undefined;
|
||||
@@ -296,14 +249,12 @@ export default function Events() {
|
||||
severity: selectedReview.severity,
|
||||
start_time: selectedReview.start_time,
|
||||
allCameras: allCameras,
|
||||
cameraSegments: allReviews.filter((seg) =>
|
||||
allCameras.includes(seg.camera),
|
||||
),
|
||||
cameraSegments: reviews.filter((seg) => allCameras.includes(seg.camera)),
|
||||
};
|
||||
|
||||
// previews will not update after item is selected
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedReviewId, reviewPages]);
|
||||
}, [selectedReviewId, reviews]);
|
||||
|
||||
if (!timezone) {
|
||||
return <ActivityIndicator />;
|
||||
@@ -335,16 +286,13 @@ export default function Events() {
|
||||
} else {
|
||||
return (
|
||||
<EventView
|
||||
reviewPages={reviewPages}
|
||||
reviews={reviews}
|
||||
reviewSummary={reviewSummary}
|
||||
relevantPreviews={allPreviews}
|
||||
timeRange={selectedTimeRange}
|
||||
reachedEnd={isDone}
|
||||
isValidating={isValidating}
|
||||
filter={reviewFilter}
|
||||
severity={severity ?? "alert"}
|
||||
setSeverity={setSeverity}
|
||||
loadNextPage={onLoadNextPage}
|
||||
markItemAsReviewed={markItemAsReviewed}
|
||||
onOpenReview={setSelectedReviewId}
|
||||
pullLatestData={reloadData}
|
||||
|
||||
Reference in New Issue
Block a user